com.mifos.mifosxdroid.online.clientlist.ClientListFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.mifos.mifosxdroid.online.clientlist.ClientListFragment.java

Source

/*
 * This project is licensed under the open source MPL V2.
 * See https://github.com/openMF/android-client/blob/master/LICENSE.md
 */

package com.mifos.mifosxdroid.online.clientlist;

import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.mifos.mifosxdroid.R;
import com.mifos.mifosxdroid.adapters.ClientNameListAdapter;
import com.mifos.mifosxdroid.core.EndlessRecyclerOnScrollListener;
import com.mifos.mifosxdroid.core.MifosBaseActivity;
import com.mifos.mifosxdroid.core.MifosBaseFragment;
import com.mifos.mifosxdroid.core.RecyclerItemClickListener;
import com.mifos.mifosxdroid.core.RecyclerItemClickListener.OnItemClickListener;
import com.mifos.mifosxdroid.core.util.Toaster;
import com.mifos.mifosxdroid.dialogfragments.syncclientsdialog.SyncClientsDialogFragment;
import com.mifos.mifosxdroid.online.ClientActivity;
import com.mifos.mifosxdroid.online.createnewclient.CreateNewClientFragment;
import com.mifos.objects.client.Client;
import com.mifos.utils.Constants;
import com.mifos.utils.FragmentConstants;

import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

/**
 * Created by ishankhanna on 09/02/14.
 * <p>
 * This class loading client, Here is two way to load the clients. First one to load clients
 * from Rest API
 * <p>
 * </>demo.openmf.org/fineract-provider/api/v1/clients?paged=true&offset=offset_value&limit
 * =limit_value</>
 * <p>
 * Offset : From Where index, client will be fetch.
 * limit : Total number of client, need to fetch
 * <p>
 * and showing in the ClientList.
 * <p>
 * and Second one is showing Group Clients. Here Group load the ClientList and send the
 * Client to ClientListFragment newInstance(List<Client> clientList,
 * boolean isParentFragment) {...}
 * and unregister the ScrollListener and SwipeLayout.
 */
public class ClientListFragment extends MifosBaseFragment
        implements OnItemClickListener, ClientListMvpView, SwipeRefreshLayout.OnRefreshListener {

    public static final String LOG_TAG = ClientListFragment.class.getSimpleName();

    @BindView(R.id.rv_clients)
    RecyclerView rv_clients;

    @BindView(R.id.swipe_container)
    SwipeRefreshLayout swipeRefreshLayout;

    @BindView(R.id.noClientText)
    TextView mNoClientText;

    @BindView(R.id.rl_error)
    RelativeLayout rlError;

    @BindView(R.id.noClientIcon)
    ImageView mNoClientIcon;

    @Inject
    ClientNameListAdapter mClientNameListAdapter;

    @Inject
    ClientListPresenter mClientListPresenter;

    private View rootView;
    private List<Client> clientList;
    private List<Client> selectedClients;
    private ActionModeCallback actionModeCallback;
    private ActionMode actionMode;
    private Boolean isParentFragment = false;
    private LinearLayoutManager mLayoutManager;

    @Override
    public void onItemClick(View childView, int position) {
        if (actionMode != null) {
            toggleSelection(position);
        } else {
            Intent clientActivityIntent = new Intent(getActivity(), ClientActivity.class);
            clientActivityIntent.putExtra(Constants.CLIENT_ID, clientList.get(position).getId());
            startActivity(clientActivityIntent);
        }
    }

    @Override
    public void onItemLongPress(View childView, int position) {
        if (actionMode == null) {
            actionMode = ((MifosBaseActivity) getActivity()).startSupportActionMode(actionModeCallback);
        }
        toggleSelection(position);
    }

    /**
     * This method will be called, whenever ClientListFragment will not have Parent Fragment.
     * So, Presenter make the call to Rest API and fetch the Client List and show in UI
     *
     * @return ClientListFragment
     */
    public static ClientListFragment newInstance() {
        Bundle arguments = new Bundle();
        ClientListFragment clientListFragment = new ClientListFragment();
        clientListFragment.setArguments(arguments);
        return clientListFragment;
    }

    /**
     * This Method will be called, whenever Parent (Fragment or Activity) will be true and Presenter
     * do not need to make Rest API call to server. Parent (Fragment or Activity) already fetched
     * the clients and for showing, they call ClientListFragment.
     * <p>
     * Example : Showing Group Clients.
     *
     * @param clientList       List<Client>
     * @param isParentFragment true
     * @return ClientListFragment
     */
    public static ClientListFragment newInstance(List<Client> clientList, boolean isParentFragment) {
        ClientListFragment clientListFragment = new ClientListFragment();
        Bundle args = new Bundle();
        if (isParentFragment && clientList != null) {
            args.putParcelableArrayList(Constants.CLIENTS, (ArrayList<? extends Parcelable>) clientList);
            args.putBoolean(Constants.IS_A_PARENT_FRAGMENT, true);
            clientListFragment.setArguments(args);
        }
        return clientListFragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ((MifosBaseActivity) getActivity()).getActivityComponent().inject(this);
        clientList = new ArrayList<>();
        selectedClients = new ArrayList<>();
        actionModeCallback = new ActionModeCallback();
        if (getArguments() != null) {
            clientList = getArguments().getParcelableArrayList(Constants.CLIENTS);
            isParentFragment = getArguments().getBoolean(Constants.IS_A_PARENT_FRAGMENT);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_client, container, false);
        setHasOptionsMenu(true);
        setToolbarTitle(getResources().getString(R.string.clients));

        ButterKnife.bind(this, rootView);
        mClientListPresenter.attachView(this);

        //setting all the UI content to the view
        showUserInterface();

        /**
         * This is the LoadMore of the RecyclerView. It called When Last Element of RecyclerView
         * is shown on the Screen.
         */
        rv_clients.addOnScrollListener(new EndlessRecyclerOnScrollListener(mLayoutManager) {
            @Override
            public void onLoadMore(int current_page) {
                mClientListPresenter.loadClients(true, clientList.size());
            }
        });

        /**
         * First Check the Parent Fragment is true or false. If parent fragment is true then no
         * need to fetch clientList from Rest API, just need to showing parent fragment ClientList
         * and is Parent Fragment is false then Presenter make the call to Rest API and fetch the
         * Client Lis to show. and Presenter make transaction to Database to load saved clients.
         */
        if (isParentFragment) {
            mClientListPresenter.showParentClients(clientList);
        } else {
            mClientListPresenter.loadClients(false, 0);
        }
        mClientListPresenter.loadDatabaseClients();

        return rootView;
    }

    /**
     * This method initializes the all Views.
     */
    @Override
    public void showUserInterface() {
        mLayoutManager = new LinearLayoutManager(getActivity());
        mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        mClientNameListAdapter.setContext(getActivity());
        rv_clients.setLayoutManager(mLayoutManager);
        rv_clients.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), this));
        rv_clients.setHasFixedSize(true);
        rv_clients.setAdapter(mClientNameListAdapter);
        swipeRefreshLayout
                .setColorSchemeColors(getActivity().getResources().getIntArray(R.array.swipeRefreshColors));
        swipeRefreshLayout.setOnRefreshListener(this);
    }

    @OnClick(R.id.fab_create_client)
    void onClickCreateNewClient() {
        ((MifosBaseActivity) getActivity()).replaceFragment(CreateNewClientFragment.newInstance(), true,
                R.id.container);
    }

    /**
     * This method will be called when user will swipe down to Refresh the ClientList then
     * Presenter make the Fresh call to Rest API to load ClientList from offset = 0 and fetch the
     * first 100 clients and update the client list.
     */
    @Override
    public void onRefresh() {
        mClientListPresenter.loadClients(false, 0);
        mClientListPresenter.loadDatabaseClients();
        if (actionMode != null)
            actionMode.finish();
    }

    /**
     * This Method unregister the RecyclerView OnScrollListener and SwipeRefreshLayout
     * and NoClientIcon click event.
     */
    @Override
    public void unregisterSwipeAndScrollListener() {
        rv_clients.clearOnScrollListeners();
        swipeRefreshLayout.setEnabled(false);
        mNoClientIcon.setEnabled(false);
    }

    /**
     * This Method showing the Simple Taster Message to user.
     *
     * @param message String Message to show.
     */
    @Override
    public void showMessage(int message) {
        Toaster.show(rootView, getStringMessage(message));
    }

    /**
     * Onclick Send Fresh Request for Client list.
     */
    @OnClick(R.id.noClientIcon)
    public void reloadOnError() {
        rlError.setVisibility(View.GONE);
        rv_clients.setVisibility(View.VISIBLE);
        mClientListPresenter.loadClients(false, 0);
        mClientListPresenter.loadDatabaseClients();
    }

    /**
     * Setting ClientList to the Adapter and updating the Adapter.
     */
    @Override
    public void showClientList(List<Client> clients) {
        clientList = clients;
        mClientNameListAdapter.setClients(clients);
        mClientNameListAdapter.notifyDataSetChanged();
    }

    /**
     * Updating Adapter Attached ClientList
     *
     * @param clients List<Client></>
     */
    @Override
    public void showLoadMoreClients(List<Client> clients) {
        clientList.addAll(clients);
        mClientNameListAdapter.notifyDataSetChanged();
    }

    /**
     * Showing Fetched ClientList size is 0 and show there is no client to show.
     *
     * @param message String Message to show user.
     */
    @Override
    public void showEmptyClientList(int message) {
        rv_clients.setVisibility(View.GONE);
        rlError.setVisibility(View.VISIBLE);
        mNoClientText.setText(getStringMessage(message));
    }

    /**
     * This Method Will be called. When Presenter failed to First page of ClientList from Rest API.
     * Then user look the Message that failed to fetch clientList.
     */
    @Override
    public void showError() {
        rv_clients.setVisibility(View.GONE);
        rlError.setVisibility(View.VISIBLE);
        String errorMessage = getStringMessage(R.string.failed_to_load_client) + getStringMessage(R.string.new_line)
                + getStringMessage(R.string.click_to_refresh);
        mNoClientText.setText(errorMessage);
    }

    /**
     * show MifosBaseActivity ProgressBar, if mClientNameListAdapter.getItemCount() == 0
     * otherwise show SwipeRefreshLayout.
     */
    @Override
    public void showProgressbar(boolean show) {
        swipeRefreshLayout.setRefreshing(show);
        if (show && mClientNameListAdapter.getItemCount() == 0) {
            showMifosProgressBar();
            swipeRefreshLayout.setRefreshing(false);
        } else {
            hideMifosProgressBar();
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        hideMifosProgressBar();
        mClientListPresenter.detachView();
        //As the Fragment Detach Finish the ActionMode
        if (actionMode != null)
            actionMode.finish();
    }

    /**
     * Toggle the selection state of an item.
     * <p>
     * If the item was the last one in the selection and is unselected, the selection is stopped.
     * Note that the selection must already be started (actionMode must not be null).
     *
     * @param position Position of the item to toggle the selection state
     */
    private void toggleSelection(int position) {
        mClientNameListAdapter.toggleSelection(position);
        int count = mClientNameListAdapter.getSelectedItemCount();

        if (count == 0) {
            actionMode.finish();
        } else {
            actionMode.setTitle(String.valueOf(count));
            actionMode.invalidate();
        }
    }

    /**
     * This ActionModeCallBack Class handling the User Event after the Selection of Clients. Like
     * Click of Menu Sync Button and finish the ActionMode
     */
    private class ActionModeCallback implements ActionMode.Callback {
        @SuppressWarnings("unused")
        private final String LOG_TAG = ActionModeCallback.class.getSimpleName();

        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            mode.getMenuInflater().inflate(R.menu.menu_sync, menu);
            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()) {
            case R.id.action_sync:

                selectedClients.clear();
                for (Integer position : mClientNameListAdapter.getSelectedItems()) {
                    selectedClients.add(clientList.get(position));
                }

                SyncClientsDialogFragment syncClientsDialogFragment = SyncClientsDialogFragment
                        .newInstance(selectedClients);
                FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager()
                        .beginTransaction();
                fragmentTransaction.addToBackStack(FragmentConstants.FRAG_CLIENT_SYNC);
                syncClientsDialogFragment.setCancelable(false);
                syncClientsDialogFragment.show(fragmentTransaction,
                        getResources().getString(R.string.sync_clients));
                mode.finish();
                return true;

            default:
                return false;
            }
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {
            mClientNameListAdapter.clearSelection();
            actionMode = null;
        }
    }
}