Forráskód Böngészése

About resolving #2953 (#3857)

About resolving #2953
Tobias Kaminsky 5 éve
szülő
commit
74a21c0217

+ 78 - 119
src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.java

@@ -35,9 +35,6 @@ import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.view.MenuItem;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ListView;
 
 import com.evernote.android.job.JobRequest;
 import com.evernote.android.job.util.support.PersistableBundleCompat;
@@ -50,7 +47,6 @@ import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.jobs.AccountRemovalJob;
-import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.services.OperationsService;
 import com.owncloud.android.ui.adapter.AccountListAdapter;
@@ -73,6 +69,8 @@ import javax.inject.Inject;
 
 import androidx.core.content.ContextCompat;
 import androidx.core.graphics.drawable.DrawableCompat;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
 
 /**
  * An Activity that allows the user to manage accounts.
@@ -85,22 +83,19 @@ public class ManageAccountsActivity extends FileActivity
     public static final String KEY_CURRENT_ACCOUNT_CHANGED = "CURRENT_ACCOUNT_CHANGED";
     public static final String PENDING_FOR_REMOVAL = UserAccountManager.PENDING_FOR_REMOVAL;
 
-    private static final String KEY_DISPLAY_NAME = "DISPLAY_NAME";
-
-    private static final int KEY_USER_INFO_REQUEST_CODE = 13;
     private static final int KEY_DELETE_CODE = 101;
     private static final int SINGLE_ACCOUNT = 1;
     private static final int MIN_MULTI_ACCOUNT_SIZE = 2;
 
-    private ListView mListView;
-    private final Handler mHandler = new Handler();
-    private String mAccountName;
-    private AccountListAdapter mAccountListAdapter;
-    private ServiceConnection mDownloadServiceConnection;
-    private ServiceConnection mUploadServiceConnection;
-    private Set<String> mOriginalAccounts;
-    private String mOriginalCurrentAccount;
-    private Drawable mTintedCheck;
+    private RecyclerView recyclerView;
+    private final Handler handler = new Handler();
+    private String accountName;
+    private AccountListAdapter accountListAdapter;
+    private ServiceConnection downloadServiceConnection;
+    private ServiceConnection uploadServiceConnection;
+    private Set<String> originalAccounts;
+    private String originalCurrentAccount;
+    private Drawable tintedCheck;
 
     private ArbitraryDataProvider arbitraryDataProvider;
 
@@ -110,24 +105,24 @@ public class ManageAccountsActivity extends FileActivity
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        mTintedCheck = DrawableCompat.wrap(ContextCompat.getDrawable(this, R.drawable.account_circle_white));
+        tintedCheck = DrawableCompat.wrap(ContextCompat.getDrawable(this, R.drawable.account_circle_white));
         int tint = ThemeUtils.elementColor(this);
-        DrawableCompat.setTint(mTintedCheck, tint);
+        DrawableCompat.setTint(tintedCheck, tint);
 
         setContentView(R.layout.accounts_layout);
 
-        mListView = findViewById(R.id.account_list);
+        recyclerView = findViewById(R.id.account_list);
 
         setupToolbar();
         updateActionBarTitleAndHomeButtonByString(getResources().getString(R.string.prefs_manage_accounts));
 
         Account[] accountList = AccountManager.get(this).getAccountsByType(MainApp.getAccountType(this));
-        mOriginalAccounts = DisplayUtils.toAccountNameSet(Arrays.asList(accountList));
+        originalAccounts = DisplayUtils.toAccountNameSet(Arrays.asList(accountList));
 
         Account currentAccount = getUserAccountManager().getCurrentAccount();
 
         if (currentAccount != null) {
-            mOriginalCurrentAccount = currentAccount.name;
+            originalCurrentAccount = currentAccount.name;
         }
 
         setAccount(currentAccount);
@@ -135,51 +130,23 @@ public class ManageAccountsActivity extends FileActivity
 
         arbitraryDataProvider = new ArbitraryDataProvider(getContentResolver());
 
-        mAccountListAdapter = new AccountListAdapter(this, getUserAccountManager(), getAccountListItems(), mTintedCheck);
-
-        mListView.setAdapter(mAccountListAdapter);
-
-        final Intent intent = new Intent(this, UserInfoActivity.class);
-
-        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
-            @Override
-            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-                AccountListItem item = mAccountListAdapter.getItem(position);
-
-                if (item != null && item.isEnabled()) {
-                    Account account = item.getAccount();
-                    intent.putExtra(UserInfoActivity.KEY_ACCOUNT, Parcels.wrap(account));
-                    try {
-                        OwnCloudAccount oca = new OwnCloudAccount(account, MainApp.getAppContext());
-                        intent.putExtra(KEY_DISPLAY_NAME, oca.getDisplayName());
-                    } catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException e) {
-                        Log_OC.d(TAG, "Failed to find NC account");
-                    }
-
-                    startActivityForResult(intent, KEY_USER_INFO_REQUEST_CODE);
-                }
-            }
-        });
+        accountListAdapter = new AccountListAdapter(this, accountManager, getAccountListItems(), tintedCheck);
 
+        recyclerView.setAdapter(accountListAdapter);
+        recyclerView.setLayoutManager(new LinearLayoutManager(this));
         initializeComponentGetters();
     }
 
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
-        switch (resultCode) {
-            case KEY_DELETE_CODE:
-                if (data != null) {
-                    Bundle bundle = data.getExtras();
-                    if (bundle.containsKey(UserInfoActivity.KEY_ACCOUNT)) {
-                        Account account = Parcels.unwrap(bundle.getParcelable(UserInfoActivity.KEY_ACCOUNT));
-                        mAccountName = account.name;
-                        performAccountRemoval(account);
-                    }
-                }
-                break;
-            default:
-                break;
+        if (resultCode == KEY_DELETE_CODE && data != null) {
+            Bundle bundle = data.getExtras();
+            if (bundle != null && bundle.containsKey(UserInfoActivity.KEY_ACCOUNT)) {
+                Account account = Parcels.unwrap(bundle.getParcelable(UserInfoActivity.KEY_ACCOUNT));
+                accountName = account.name;
+                performAccountRemoval(account);
+            }
         }
     }
 
@@ -211,7 +178,7 @@ public class ManageAccountsActivity extends FileActivity
         }
 
         Set<String> actualAccounts = DisplayUtils.toAccountNameSet(newList);
-        return !mOriginalAccounts.equals(actualAccounts);
+        return !originalAccounts.equals(actualAccounts);
     }
 
     /**
@@ -224,7 +191,7 @@ public class ManageAccountsActivity extends FileActivity
         if (account == null) {
             return true;
         } else {
-            return !account.name.equals(mOriginalCurrentAccount);
+            return !account.name.equals(originalCurrentAccount);
         }
     }
 
@@ -232,15 +199,15 @@ public class ManageAccountsActivity extends FileActivity
      * Initialize ComponentsGetters.
      */
     private void initializeComponentGetters() {
-        mDownloadServiceConnection = newTransferenceServiceConnection();
-        if (mDownloadServiceConnection != null) {
-            bindService(new Intent(this, FileDownloader.class), mDownloadServiceConnection,
-                    Context.BIND_AUTO_CREATE);
+        downloadServiceConnection = newTransferenceServiceConnection();
+        if (downloadServiceConnection != null) {
+            bindService(new Intent(this, FileDownloader.class), downloadServiceConnection,
+                        Context.BIND_AUTO_CREATE);
         }
-        mUploadServiceConnection = newTransferenceServiceConnection();
-        if (mUploadServiceConnection != null) {
-            bindService(new Intent(this, FileUploader.class), mUploadServiceConnection,
-                    Context.BIND_AUTO_CREATE);
+        uploadServiceConnection = newTransferenceServiceConnection();
+        if (uploadServiceConnection != null) {
+            bindService(new Intent(this, FileUploader.class), uploadServiceConnection,
+                        Context.BIND_AUTO_CREATE);
         }
     }
 
@@ -290,54 +257,46 @@ public class ManageAccountsActivity extends FileActivity
     public void createAccount() {
         AccountManager am = AccountManager.get(getApplicationContext());
         am.addAccount(MainApp.getAccountType(this),
-                null,
-                null,
-                null,
-                this,
-                new AccountManagerCallback<Bundle>() {
-                    @Override
-                    public void run(AccountManagerFuture<Bundle> future) {
-                        if (future != null) {
-                            try {
-                                Bundle result = future.getResult();
-                                String name = result.getString(AccountManager.KEY_ACCOUNT_NAME);
-                                accountManager.setCurrentOwnCloudAccount(name);
-                                mAccountListAdapter = new AccountListAdapter(
-                                        ManageAccountsActivity.this,
-                                        getUserAccountManager(),
-                                        getAccountListItems(),
-                                        mTintedCheck
-                                );
-                                mListView.setAdapter(mAccountListAdapter);
-                                runOnUiThread(new Runnable() {
-                                    @Override
-                                    public void run() {
-                                        mAccountListAdapter.notifyDataSetChanged();
-                                    }
-                                });
-                            } catch (OperationCanceledException e) {
-                                Log_OC.d(TAG, "Account creation canceled");
-                            } catch (Exception e) {
-                                Log_OC.e(TAG, "Account creation finished in exception: ", e);
-                            }
-                        }
-                    }
-                }, mHandler);
+                      null,
+                      null,
+                      null,
+                      this,
+                      future -> {
+                          if (future != null) {
+                              try {
+                                  Bundle result = future.getResult();
+                                  String name = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+                                  accountManager.setCurrentOwnCloudAccount(name);
+                                  accountListAdapter = new AccountListAdapter(
+                                          this,
+                                          accountManager,
+                                          getAccountListItems(),
+                                          tintedCheck
+                                  );
+                                  recyclerView.setAdapter(accountListAdapter);
+                                  runOnUiThread(() -> accountListAdapter.notifyDataSetChanged());
+                              } catch (OperationCanceledException e) {
+                                  Log_OC.d(TAG, "Account creation canceled");
+                              } catch (Exception e) {
+                                  Log_OC.e(TAG, "Account creation finished in exception: ", e);
+                              }
+                          }
+                      }, handler);
     }
 
     @Subscribe(threadMode = ThreadMode.MAIN)
     public void onAccountRemovedEvent(AccountRemovedEvent event) {
         List<AccountListItem> accountListItemArray = getAccountListItems();
-        mAccountListAdapter.clear();
-        mAccountListAdapter.addAll(accountListItemArray);
-        mAccountListAdapter.notifyDataSetChanged();
+        accountListAdapter.clear();
+        accountListAdapter.addAll(accountListItemArray);
+        accountListAdapter.notifyDataSetChanged();
     }
 
     @Override
     public void run(AccountManagerFuture<Boolean> future) {
         if (future.isDone()) {
             // after remove account
-            Account account = new Account(mAccountName, MainApp.getAccountType(this));
+            Account account = new Account(accountName, MainApp.getAccountType(this));
             if (!accountManager.exists(account)) {
                 // Cancel transfers of the removed account
                 if (mUploaderBinder != null) {
@@ -359,8 +318,8 @@ public class ManageAccountsActivity extends FileActivity
 
             List<AccountListItem> accountListItemArray = getAccountListItems();
             if (accountListItemArray.size() > SINGLE_ACCOUNT) {
-                mAccountListAdapter = new AccountListAdapter(this, getUserAccountManager(), accountListItemArray, mTintedCheck);
-                mListView.setAdapter(mAccountListAdapter);
+                accountListAdapter = new AccountListAdapter(this, accountManager, accountListItemArray, tintedCheck);
+                recyclerView.setAdapter(accountListAdapter);
             } else {
                 onBackPressed();
             }
@@ -369,19 +328,19 @@ public class ManageAccountsActivity extends FileActivity
 
     @Override
     protected void onDestroy() {
-        if (mDownloadServiceConnection != null) {
-            unbindService(mDownloadServiceConnection);
-            mDownloadServiceConnection = null;
+        if (downloadServiceConnection != null) {
+            unbindService(downloadServiceConnection);
+            downloadServiceConnection = null;
         }
-        if (mUploadServiceConnection != null) {
-            unbindService(mUploadServiceConnection);
-            mUploadServiceConnection = null;
+        if (uploadServiceConnection != null) {
+            unbindService(uploadServiceConnection);
+            uploadServiceConnection = null;
         }
 
         super.onDestroy();
     }
 
-    public Handler getHandler() { return mHandler; }
+    public Handler getHandler() { return handler; }
 
     @Override
     public FileUploader.FileUploaderBinder getFileUploaderBinder() {
@@ -408,16 +367,16 @@ public class ManageAccountsActivity extends FileActivity
     }
 
     private void performAccountRemoval(Account account) {
-        // disable account in list view
-        for (int i = 0; i < mAccountListAdapter.getCount(); i++) {
-            AccountListItem item = mAccountListAdapter.getItem(i);
+        // disable account in recycler view
+        for (int i = 0; i < accountListAdapter.getItemCount(); i++) {
+            AccountListItem item = accountListAdapter.getItem(i);
 
             if (item != null && item.getAccount().equals(account)) {
                 item.setEnabled(false);
                 break;
             }
 
-            mAccountListAdapter.notifyDataSetChanged();
+            accountListAdapter.notifyDataSetChanged();
         }
 
         // store pending account removal

+ 2 - 1
src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java

@@ -58,6 +58,7 @@ import android.widget.Button;
 import android.widget.EditText;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
+import android.widget.ListAdapter;
 import android.widget.ListView;
 import android.widget.ProgressBar;
 import android.widget.Spinner;
@@ -309,7 +310,7 @@ public class ReceiveExternalFilesActivity extends FileActivity
             mAccountListAdapter = new AccountListAdapter(parent, accountManager, getAccountListItems(parent), mTintedCheck);
 
             builder.setTitle(R.string.common_choose_account);
-            builder.setAdapter(mAccountListAdapter, (dialog, which) -> {
+            builder.setAdapter((ListAdapter) mAccountListAdapter, (dialog, which) -> {
                 final ReceiveExternalFilesActivity parentActivity = (ReceiveExternalFilesActivity) getActivity();
                 parentActivity.setAccount(parentActivity.mAccountManager.getAccountsByType(
                         MainApp.getAccountType(getActivity()))[which], false);

+ 193 - 79
src/main/java/com/owncloud/android/ui/adapter/AccountListAdapter.java

@@ -1,107 +1,140 @@
 /*
- * ownCloud Android client application
+ *   Nextcloud Android client application
  *
- * @author Andy Scherzinger
- * @author Chris Narkiewicz
- * Copyright (C) 2016 ownCloud Inc.
- * Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
- * <p/>
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- * <p/>
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * <p/>
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *   @author Andy Scherzinger
+ *   @author Chris Narkiewicz
+ *   @author Nick Antoniou
+ *   Copyright (C) 2016 Andy Scherzinger
+ *   Copyright (C) 2016 ownCloud Inc.
+ *   Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
+ *   Copyright (C) 2019 Nick Antoniou
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ *   License as published by the Free Software Foundation; either
+ *   version 3 of the License, or any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ *   You should have received a copy of the GNU Affero General Public
+ *   License along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 package com.owncloud.android.ui.adapter;
 
 import android.accounts.Account;
+import android.content.Intent;
 import android.graphics.Paint;
 import android.graphics.drawable.Drawable;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
 import android.widget.ImageView;
 import android.widget.TextView;
 
 import com.nextcloud.client.account.UserAccountManager;
+import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.ui.activity.BaseActivity;
+import com.owncloud.android.ui.activity.UserInfoActivity;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.ThemeUtils;
 
+import org.parceler.Parcels;
+
+import java.util.ArrayList;
 import java.util.List;
 
 import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
 
 /**
- * This Adapter populates a ListView with all accounts within the app.
+ * This Adapter populates a RecyclerView with all accounts within the app.
  */
-public class AccountListAdapter extends ArrayAdapter<AccountListItem> implements DisplayUtils.AvatarGenerationListener {
+public class AccountListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
+                                implements DisplayUtils.AvatarGenerationListener {
     private static final String TAG = AccountListAdapter.class.getSimpleName();
-    private float mAccountAvatarRadiusDimension;
-    private final BaseActivity mContext;
-    private List<AccountListItem> mValues;
-    private AccountListAdapterListener mListener;
-    private Drawable mTintedCheck;
+
+    private float accountAvatarRadiusDimension;
+    private final BaseActivity context;
+    private List<AccountListItem> values;
+    private AccountListAdapterListener accountListAdapterListener;
+    private Drawable tintedCheck;
     private UserAccountManager accountManager;
 
+    private static final String KEY_DISPLAY_NAME = "DISPLAY_NAME";
+    private static final int KEY_USER_INFO_REQUEST_CODE = 13;
+
     public AccountListAdapter(BaseActivity context, UserAccountManager accountManager, List<AccountListItem> values, Drawable tintedCheck) {
-        super(context, -1, values);
-        this.mContext = context;
+        this.context = context;
         this.accountManager = accountManager;
-        this.mValues = values;
+        this.values = values;
         if (context instanceof AccountListAdapterListener) {
-            this.mListener = (AccountListAdapterListener) context;
+            this.accountListAdapterListener = (AccountListAdapterListener) context;
+        }
+        this.accountAvatarRadiusDimension = context.getResources().getDimension(R.dimen.list_item_avatar_icon_radius);
+        this.tintedCheck = tintedCheck;
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        if (position == values.size() - 1) {
+            return AccountListItem.TYPE_ACTION_ADD;
         }
-        this.mAccountAvatarRadiusDimension = context.getResources().getDimension(R.dimen.list_item_avatar_icon_radius);
-        this.mTintedCheck = tintedCheck;
+        return AccountListItem.TYPE_ACCOUNT;
     }
 
-    @NonNull
     @Override
-    public View getView(final int position, View convertView, @NonNull ViewGroup parent) {
-        AccountViewHolderItem viewHolder;
-        View view = convertView;
-
-        if (view == null) {
-            LayoutInflater inflater = mContext.getLayoutInflater();
-            view = inflater.inflate(R.layout.account_item, parent, false);
-
-            viewHolder = new AccountViewHolderItem();
-            viewHolder.imageViewItem = view.findViewById(R.id.user_icon);
-            viewHolder.checkViewItem = view.findViewById(R.id.ticker);
-            viewHolder.checkViewItem.setImageDrawable(mTintedCheck);
-            viewHolder.usernameViewItem = view.findViewById(R.id.user_name);
-            viewHolder.accountViewItem = view.findViewById(R.id.account);
-
-            view.setTag(viewHolder);
+    public @NonNull
+    RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+        View view;
+        if (AccountListItem.TYPE_ACCOUNT == viewType) {
+            view = LayoutInflater.from(context).inflate(R.layout.account_item, parent, false);
+            AccountViewHolderItem viewHolder = new AccountViewHolderItem(view);
+            viewHolder.checkViewItem.setImageDrawable(tintedCheck);
+            return viewHolder;
         } else {
-            viewHolder = (AccountViewHolderItem) view.getTag();
+            view = LayoutInflater.from(context).inflate(R.layout.account_action, parent, false);
+            return new AddAccountViewHolderItem(view);
         }
+    }
 
-        AccountListItem accountListItem = mValues.get(position);
+    @Override
+    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
+        AccountListItem accountListItem = values.get(position);
 
         if (accountListItem != null) {
             // create account item
             if (AccountListItem.TYPE_ACCOUNT == accountListItem.getType()) {
                 Account account = accountListItem.getAccount();
-                setAccount(viewHolder, account);
-                setUsername(viewHolder, account);
-                setAvatar(viewHolder, account);
-                setCurrentlyActiveState(viewHolder, account);
-
-                TextView usernameView = viewHolder.usernameViewItem;
-                TextView accountView = viewHolder.accountViewItem;
+                AccountViewHolderItem item = (AccountViewHolderItem)holder;
+                setAccount(item, account);
+                setUsername(item, account);
+                setAvatar(item, account);
+                setCurrentlyActiveState(item, account);
+
+                TextView usernameView = item.usernameViewItem;
+                TextView accountView = item.accountViewItem;
+
+                // OnClickListener for when the user selects an account
+                holder.itemView.setOnClickListener(view -> {
+                    final Intent intent = new Intent(context, UserInfoActivity.class);
+                    if (accountListItem.isEnabled()) {
+                        intent.putExtra(UserInfoActivity.KEY_ACCOUNT, Parcels.wrap(account));
+                        try {
+                            OwnCloudAccount oca = new OwnCloudAccount(account, MainApp.getAppContext());
+                            intent.putExtra(KEY_DISPLAY_NAME, oca.getDisplayName());
+                        } catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException e) {
+                            Log_OC.d(TAG, "Failed to find NC account");
+                        }
+                        context.startActivityForResult(intent, KEY_USER_INFO_REQUEST_CODE);
+                    }
+                });
 
                 if (!accountListItem.isEnabled()) {
                     usernameView.setPaintFlags(usernameView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
@@ -112,43 +145,51 @@ public class AccountListAdapter extends ArrayAdapter<AccountListItem> implements
                 }
 
             } // create add account action item
-            else if (AccountListItem.TYPE_ACTION_ADD == accountListItem.getType() && mListener != null) {
-                return setupAddAccountListItem(parent);
+            else if (AccountListItem.TYPE_ACTION_ADD == accountListItem.getType() && accountListAdapterListener != null) {
+                setupAddAccountListItem((AddAccountViewHolderItem)holder);
             }
         }
-
-        return view;
     }
 
-    @NonNull
-    private View setupAddAccountListItem(ViewGroup parent) {
-        LayoutInflater inflater = mContext.getLayoutInflater();
-        View actionView = inflater.inflate(R.layout.account_action, parent, false);
-
-        TextView userName = actionView.findViewById(R.id.user_name);
-        userName.setText(R.string.prefs_add_account);
-        userName.setTextColor(ThemeUtils.primaryColor(getContext(), true));
+    /**
+     * Sets up a View to be used for adding a new account
+     *
+     * @param holder the add account view holder
+     */
+    private void setupAddAccountListItem(AddAccountViewHolderItem holder) {
+        View actionView = holder.itemView;
 
-        ((ImageView) actionView.findViewById(R.id.user_icon)).setImageResource(R.drawable.ic_account_plus);
+        holder.usernameViewItem.setTextColor(ThemeUtils.primaryColor(context, true));
 
         // bind action listener
-        boolean isProviderOrOwnInstallationVisible = mContext.getResources()
+        boolean isProviderOrOwnInstallationVisible = context.getResources()
                 .getBoolean(R.bool.show_provider_or_own_installation);
 
         if (isProviderOrOwnInstallationVisible) {
-            actionView.setOnClickListener(v -> mListener.showFirstRunActivity());
+            actionView.setOnClickListener(v -> accountListAdapterListener.showFirstRunActivity());
         } else {
-            actionView.setOnClickListener(v -> mListener.createAccount());
+            actionView.setOnClickListener(v -> accountListAdapterListener.createAccount());
         }
-
-        return actionView;
     }
 
+    /**
+     * Sets the name of the account, in the view holder
+     *
+     * @param viewHolder the view holder that contains the account
+     * @param account the account
+     */
     private void setAccount(AccountViewHolderItem viewHolder, Account account) {
         viewHolder.accountViewItem.setText(DisplayUtils.convertIdn(account.name, false));
         viewHolder.accountViewItem.setTag(account.name);
     }
 
+    /**
+     * Sets the current active state of the account to true if it is the account being used currently,
+     * false otherwise
+     *
+     * @param viewHolder the view holder that contains the account
+     * @param account the account
+     */
     private void setCurrentlyActiveState(AccountViewHolderItem viewHolder, Account account) {
         Account currentAccount = accountManager.getCurrentAccount();
         if (currentAccount != null && currentAccount.name.equals(account.name)) {
@@ -158,12 +199,18 @@ public class AccountListAdapter extends ArrayAdapter<AccountListItem> implements
         }
     }
 
+    /**
+     * Sets the avatar of the account
+     *
+     * @param viewHolder the view holder that contains the account
+     * @param account the account
+     */
     private void setAvatar(AccountViewHolderItem viewHolder, Account account) {
         try {
             View viewItem = viewHolder.imageViewItem;
             viewItem.setTag(account.name);
-            DisplayUtils.setAvatar(account, this, mAccountAvatarRadiusDimension, mContext.getResources(), viewItem,
-                    mContext);
+            DisplayUtils.setAvatar(account, this, accountAvatarRadiusDimension, context.getResources(), viewItem,
+                                   context);
         } catch (Exception e) {
             Log_OC.e(TAG, "Error calculating RGB value for account list item.", e);
             // use user icon as a fallback
@@ -171,9 +218,15 @@ public class AccountListAdapter extends ArrayAdapter<AccountListItem> implements
         }
     }
 
+    /**
+     * Sets the username of the account
+     *
+     * @param viewHolder the view holder that contains the account
+     * @param account the account
+     */
     private void setUsername(AccountViewHolderItem viewHolder, Account account) {
         try {
-            OwnCloudAccount oca = new OwnCloudAccount(account, mContext);
+            OwnCloudAccount oca = new OwnCloudAccount(account, context);
             viewHolder.usernameViewItem.setText(oca.getDisplayName());
         } catch (Exception e) {
             Log_OC.w(TAG, "Account not found right after being read; using account name instead");
@@ -192,6 +245,48 @@ public class AccountListAdapter extends ArrayAdapter<AccountListItem> implements
         return String.valueOf(((ImageView)callContext).getTag()).equals(tag);
     }
 
+    /**
+     * Returns the total number of items in the data set held by the adapter
+     *
+     * @return The total number of items in this adapter.
+     */
+    @Override
+    public int getItemCount() {
+        return this.values.size();
+    }
+
+    /**
+     * Returns an AccountListItem from the specified position in the values list
+     *
+     * @param position of the object to be returned
+     * @return An AccountListItem of the specified position
+     */
+    public AccountListItem getItem(int position) {
+        return values.get(position);
+    }
+
+    /**
+     * Deletes the elements in the values list and notifies the Adapter
+     */
+    public void clear() {
+        final int size = values.size();
+        values.clear();
+        notifyItemRangeRemoved(0, size);
+    }
+
+    /**
+     * Adds all of the items to the data set
+     *
+     * @param items The item list to be added
+     */
+    public void addAll(List<AccountListItem> items){
+        if(values == null){
+            values = new ArrayList<>();
+        }
+        values.addAll(items);
+        notifyDataSetChanged();
+    }
+
     /**
      * Listener interface for Activities using the {@link AccountListAdapter}
      */
@@ -205,11 +300,30 @@ public class AccountListAdapter extends ArrayAdapter<AccountListItem> implements
     /**
      * Account ViewHolderItem to get smooth scrolling.
      */
-    private static class AccountViewHolderItem {
+    static class AccountViewHolderItem extends RecyclerView.ViewHolder {
         private ImageView imageViewItem;
         private ImageView checkViewItem;
 
         private TextView usernameViewItem;
         private TextView accountViewItem;
+
+        AccountViewHolderItem(@NonNull View view) {
+            super(view);
+            this.imageViewItem = view.findViewById(R.id.user_icon);
+            this.checkViewItem = view.findViewById(R.id.ticker);
+            this.usernameViewItem = view.findViewById(R.id.user_name);
+            this.accountViewItem = view.findViewById(R.id.account);
+        }
+    }
+
+    /**
+     * Account ViewHolderItem to get smooth scrolling.
+     */
+    static class AddAccountViewHolderItem extends RecyclerView.ViewHolder {
+        private TextView usernameViewItem;
+        AddAccountViewHolderItem(@NonNull View view) {
+            super(view);
+            this.usernameViewItem = view.findViewById(R.id.user_name);
+        }
     }
 }

+ 12 - 10
src/main/java/com/owncloud/android/ui/adapter/AccountListItem.java

@@ -1,20 +1,22 @@
-/**
- *   ownCloud Android client application
+/*
+ *   Nextcloud Android client application
  *
  *   @author Andy Scherzinger
+ *   Copyright (C) 2016 Andy Scherzinger
  *   Copyright (C) 2016 ownCloud Inc.
  *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ *   License as published by the Free Software Foundation; either
+ *   version 3 of the License, or any later version.
  *
  *   This program is distributed in the hope that it will be useful,
  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
+ *   GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *   You should have received a copy of the GNU Affero General Public
+ *   License along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 package com.owncloud.android.ui.adapter;
@@ -25,8 +27,8 @@ import android.accounts.Account;
  * Container implementation to add {@link Account}s and the add action to the list.
  */
 public class AccountListItem {
-    public static final int TYPE_ACCOUNT = 0;
-    public static final int TYPE_ACTION_ADD = 1;
+    static final int TYPE_ACCOUNT = 0;
+    static final int TYPE_ACTION_ADD = 1;
 
     private Account mAccount;
     private int mType;

+ 1 - 1
src/main/res/layout/accounts_layout.xml

@@ -29,7 +29,7 @@
 	<include
 		layout="@layout/toolbar_standard"/>
 
-	<ListView
+	<androidx.recyclerview.widget.RecyclerView
 		android:id="@+id/account_list"
 		android:layout_width="fill_parent"
 		android:layout_height="fill_parent"

+ 1 - 1
src/test/java/com/owncloud/android/ui/activities/data/activities/RemoteActivitiesRepositoryTest.java

@@ -1,4 +1,4 @@
-/**
+/*
  *   Nextcloud Android client application
  *
  *   Copyright (C) 2018 Edvard Holst

+ 99 - 0
src/test/java/com/owncloud/android/ui/adapter/AccountListAdapterTest.java

@@ -0,0 +1,99 @@
+/*
+ *   Nextcloud Android client application
+ *
+ *   @author Nick Antoniou
+ *   Copyright (C) 2019 Nick Antoniou
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ *   License as published by the Free Software Foundation; either
+ *   version 3 of the License, or any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ *   You should have received a copy of the GNU Affero General Public
+ *   License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.ui.adapter;
+
+import com.owncloud.android.R;
+import com.owncloud.android.ui.activity.ManageAccountsActivity;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * Class used to test the AccountList Adapter
+ */
+public class AccountListAdapterTest {
+
+    private AccountListAdapter accountListAdapter;
+    private ManageAccountsActivity manageAccountsActivity;
+
+    /**
+     * Setting up and mocking the manageAccountsActivity class, and then mocking the method calls in the construction of
+     * the object
+     */
+    @Before
+    public void setup() {
+        manageAccountsActivity = mock(ManageAccountsActivity.class, Mockito.RETURNS_DEEP_STUBS);
+        when(manageAccountsActivity.getResources().getDimension(R.dimen.list_item_avatar_icon_radius))
+            .thenReturn(new Float(0.1));
+    }
+
+    /**
+     * Testing the getItemCount method, in the case of an empty List
+     */
+    @Test
+    public void test_getItemCountEmptyList() {
+        accountListAdapter = new AccountListAdapter(manageAccountsActivity, null,
+                                                    new ArrayList<>(), null);
+        assertEquals(0, accountListAdapter.getItemCount());
+    }
+
+    /**
+     * Testing the getItemCount method, in a normal case, of having two accounts
+     */
+    @Test
+    public void test_getItemCountNormalCase() {
+        List<AccountListItem> accounts = new ArrayList<>();
+        accounts.add(new AccountListItem());
+        accounts.add(new AccountListItem());
+
+        accountListAdapter = new AccountListAdapter(manageAccountsActivity, null, accounts, null);
+
+        assertEquals(2, accountListAdapter.getItemCount());
+    }
+
+    /**
+     * Testing a normal case of the getItem method
+     */
+    @Test
+    public void test_getItem() {
+        ManageAccountsActivity manageAccountsActivity = mock(ManageAccountsActivity.class, Mockito.RETURNS_DEEP_STUBS);
+        when(manageAccountsActivity.getResources().getDimension(R.dimen.list_item_avatar_icon_radius))
+            .thenReturn(new Float(0.1));
+
+        List<AccountListItem> accounts = new ArrayList<>();
+        accountListAdapter = new AccountListAdapter(manageAccountsActivity, null, accounts, null);
+
+        AccountListItem accountListItem1 = new AccountListItem();
+        AccountListItem accountListItem2 = new AccountListItem();
+        accounts.add(accountListItem1);
+        accounts.add(accountListItem2);
+
+        assertEquals(accountListItem2, accountListAdapter.getItem(1));
+    }
+}