简体   繁体   中英

Reset RecyclerView adapter from another Fragment

I have a Fragment that contains a RecyclerView. I am trying to implement a filter on the RecyclerView. The filter UI opens a new Fragment Dialog where the user will input a value. Once the user hits the Search Button in the Fragment Dialog, the value should be returned to the RecyclerView Fragment and the existing data in the view should be cleared. I want to re-populate the RecyclerView with the new set of data that I will obtain from the server. My problem is that, I have a method called resetAdapterDetails() in the RecyclerView Fragment which works as expected if called from the RecyclerView Fragment itself. But, when I try to call the same method from the Fragment Dialog, I get an exception:

transactionList.clear(); --> is trying to clear a list which is null

Though the data is still visible in the RecyclerView.

The RecyclerView Fragment :

public class TransactionHistoryFragment extends Fragment implements SearchView.OnQueryTextListener, DateRangePickerFragment.OnDateRangeSelectedListener{

    private RecyclerView recyclerview;
    private TransactionHistoryAdapter adapter;
    private List<Transaction> transactionList;

    public TransactionHistoryFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_transaction_history, container, false);

        recyclerview = (RecyclerView) view.findViewById(R.id.recyclerview);


        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
        recyclerview.setLayoutManager(layoutManager);
        return view;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }


    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        setHasOptionsMenu(true);
        getTransactionHistory("");
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.transactions_history_menu, menu);

        final MenuItem searchItem = menu.findItem(R.id.action_search);
        final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
        searchView.setOnQueryTextListener(this);


        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.filter_date:
                FragmentManager fmDate = getActivity().getFragmentManager();
                DateRangePickerFragment dialogFragmentDate = DateRangePickerFragment.newInstance(this, true);
                dialogFragmentDate.show(fmDate, "Sample Fragment");
                return true;
            case R.id.filter_mobile:
                FragmentManager fmMobile = getActivity().getFragmentManager();
                SearchMobileFragment dialogFragmentMobile = new SearchMobileFragment ();
                dialogFragmentMobile.show(fmMobile, "Sample Fragment");
                //resetAdapterDetails();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }

    }

    @Override
    public boolean onQueryTextChange(String newText) {
        final List<Transaction> filteredModelList = filter(transactionList, newText);

        adapter.setFilter(filteredModelList);
        return true;
    }

    @Override
    public boolean onQueryTextSubmit(String query) {
        return false;
    }

    //for filtering the list
    private List<Transaction> filter(List<Transaction> models, String query) {
        query = query.toLowerCase();final List<Transaction> filteredModelList = new ArrayList<>();
        for (Transaction model : models) {
            final String text = model.getTxnStatus().toLowerCase();
            if (text.contains(query)) {
                filteredModelList.add(model);
            }
        }
        return filteredModelList;
    }
    //for populating the list
    private void getTransactionHistory(String agentId){
        GetTransactionHistoryTask task = new GetTransactionHistoryTask("agent1", "password");
        task.getTransactionsByAgent("OU23","OU230000000123456789").subscribe(transactionHistoryResponse -> {
            if(transactionHistoryResponse != null && transactionHistoryResponse.getTransactions() != null && transactionHistoryResponse.getTransactions().size() > 0 && transactionHistoryResponse.getErrors().size() == 0){
                transactionList = transactionHistoryResponse.getTransactions();

                adapter = new TransactionHistoryAdapter(transactionList);
                recyclerview.addItemDecoration(new DividerItemDecoration(getActivity(), LinearLayoutManager.VERTICAL));
                recyclerview.setAdapter(adapter);
                onClickListnerRecyclerView();

            }
            else{

            }
        }, e -> e.printStackTrace());
    }

    private void onClickListnerRecyclerView() {
        recyclerview.addOnItemTouchListener(
                new RecyclerItemClickListener(getActivity(), new RecyclerItemClickListener.OnItemClickListener() {
                    @Override
                    public void onItemClick(View view, int position) {

                        try {
                           final Transaction transactionModel= (Transaction) adapter.getObjectAt(position);
                            Intent i = new Intent(getActivity(), TransactionDetailsActivity.class);
                            i.putExtra("transaction_object",transactionModel);
                            startActivity(i);
                        }

                        catch (Exception e){
                            Log.e("List issue", e.toString());
                        }

                    }
                })
        );
    }

    @Override
    public void onDateRangeSelected(int startDay, int startMonth, int startYear, int endDay, int endMonth, int endYear) {

    }

    public void fetchDateRange(String startDate, String endDate) {
        Log.e("DateRange",startDate + "\n" + endDate);
    }

    public void fetchMobileNumber(String mobileNumber) {
        Log.e("Mobile",mobileNumber);
        resetAdapterDetails();
    }

    public boolean resetAdapterDetails(){
        try {
            transactionList.clear();
            adapter.notifyDataSetChanged();
            recyclerview.setAdapter(adapter);

        } catch (Exception e) {
            Log.e("Reset Error", ""+e.getMessage());
        }

        return true;
    }
}

The Dialog Fragment :

public class SearchMobileFragment extends DialogFragment {

    EditText mMobileNumberEditText;
    Button search_button;

    public SearchMobileFragment() {
        // Required empty public constructor
    }



    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_search_mobile, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        mMobileNumberEditText = (EditText) view.findViewById(R.id.mobile_number_editText);
        search_button = (Button) view.findViewById(R.id.search_button);
        search_button.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {

                dismiss();
                TransactionHistoryFragment obj = new TransactionHistoryFragment();
                obj.fetchMobileNumber(mMobileNumberEditText.getText().toString());
            }
        });

    }
}

The fetchMobileNumber() method in the TransactionHistoryFragment (RecyclerView Fragment) is called through the fetchMobileNumber() method which is called from the SearchMobileFragment (Dialog Fragment) .

Where am I going wrong? Why the transactionList.clear(); is throwing the null pointer exception?

You are getting the issue because you are creating new TransactionHistoryFragment instance search_button click in SearchMobileFragment. Which makes it's all variables null and initialize it again and here your transactionList becomes null.

You can achieve the same thing easily with different way also. As the place of SearchMobileFragment as a DialogFragment you can make it as Activity and start it as startActivityForResult from your TransactionHistoryFragment and implement onActivityResult callback to doing the fiteration.

But right now in your case you can manage it in different ways also:

First way: As you are doing in your DialogFragment

search_button.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {

                dismiss();
                /*TransactionHistoryFragment obj = new TransactionHistoryFragment();
                obj.fetchMobileNumber(mMobileNumberEditText.getText().toString());*/
            }
        });

Don't do the call for fetchMobileNumber here, in onResume of your TransactionHistoryFragment you should make a call for this. On the click of search_button save the filter data to SharedPreferences and use that in onResume of the TransactionHistoryFragment for filtering and after that clear this saved data from SharedPreferences onPause of this fragment.

You should remove

transactionList.clear(); 

of code from resetAdapterDetails() in TransactionHistoryFragment, because after search filter you will get updated transactionList which is already passed to adapter then forcefully no need to clear it. Or have a check before clearing it like:

if(transactionList!=null){
   transactionList.clear();
}

Second way: Using BroadcastReceiver you can achieve the same thing. Register a receiver in your TransactionHistoryFragment and sendBroadcast from SearchMobileFragment. In onReceive of the TransactionHistoryFragment do the filtration process.

I had resolved the above issue in a different way. In the Dialog Fragment I have implemented a View.OnClickListener and have created an Interface to initialize the same from the RecyclerView Fragment . I am posting the complete source codes below; the SearchMobileFragment now looks like:

public class SearchMobileFragment extends DialogFragment implements View.OnClickListener{

    private OnMobileNumberSelectedListener onMobileNumberSelectedListener;

    EditText mMobileNumberEditText;
    Button mSearchButton;

    public SearchMobileFragment() {
        // Required empty public constructor
    }

    public static SearchMobileFragment newInstance(OnMobileNumberSelectedListener callback) {
        SearchMobileFragment searchMobileFragment = new SearchMobileFragment();
        searchMobileFragment.initialize(callback);
        return searchMobileFragment;
    }

    public void initialize(OnMobileNumberSelectedListener callback) {
        onMobileNumberSelectedListener = callback;
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_search_mobile, container, false);
        getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        mMobileNumberEditText = (EditText) root.findViewById(R.id.mobile_number_editText);
        mSearchButton = (Button) root.findViewById(R.id.search_button);
        mSearchButton.setOnClickListener(this);
        return root;
    }

    @Override
    public void onStart() {
        super.onStart();
        if (getDialog() == null)
            return;
        getDialog().getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
    }

    public void setOnMobileNumberSelectedListener(OnMobileNumberSelectedListener callback) {
        this.onMobileNumberSelectedListener = callback;
    }

    @Override
    public void onClick(View v) {
        dismiss();


        onMobileNumberSelectedListener.onMobileNumberSelected(mMobileNumberEditText.getText().toString());

    }



    public interface OnMobileNumberSelectedListener {
        void onMobileNumberSelected(String mobileNumber);
    }
}

The RecyclerView Fragment modifications:

public class TransactionHistoryFragment extends Fragment implements SearchView.OnQueryTextListener,
        DateRangePickerFragment.OnDateRangeSelectedListener, SearchMobileFragment.OnMobileNumberSelectedListener{

    private RecyclerView recyclerview;
    private TransactionHistoryAdapter adapter;
    private List<Transaction> transactionList;

    SearchView search;

    public static final String TIMERANGEPICKER_TAG = "timerangepicker";



    public TransactionHistoryFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_transaction_history, container, false);

        recyclerview = (RecyclerView) view.findViewById(R.id.recyclerview);


        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
        recyclerview.setLayoutManager(layoutManager);
        return view;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }



    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        setHasOptionsMenu(true);
        getTransactionHistory();
    }

    @Override
    public void onResume() {
        Log.e("onResumeTHF","invoked");
        super.onResume();
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.transactions_history_menu, menu);
        search = (SearchView) menu.findItem(R.id.action_search).getActionView();
        search.setOnQueryTextListener(this);

        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.filter_date:
                FragmentManager fmDate = getActivity().getFragmentManager();
                DateRangePickerFragment dialogFragmentDate = DateRangePickerFragment.newInstance(this, true);
                dialogFragmentDate.show(fmDate, "Sample Fragment");
                return true;
            case R.id.filter_mobile:
                FragmentManager fmMobile = getActivity().getFragmentManager();
                SearchMobileFragment dialogFragmentMobile = SearchMobileFragment.newInstance(this);
                dialogFragmentMobile.show(fmMobile, "Sample Fragment");
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }

    }

    @Override
    public boolean onQueryTextChange(String newText) {
        Log.e("newText",newText);
       final List<Transaction> filteredModelList = filter(transactionList, newText);

        adapter.setFilter(filteredModelList);
        return true;
    }

    @Override
    public boolean onQueryTextSubmit(String query) {
        return false;
    }




    @Override
    public void onMobileNumberSelected(String mobileNumber) {

        Log.e("mobileNumber",mobileNumber);

        resetAdapterDetails();
    }


    public boolean resetAdapterDetails(){
        try {
            transactionList.clear();
            adapter.notifyDataSetChanged();
            recyclerview.setAdapter(adapter);

        } catch (Exception e) {
            Log.e("Reset Error", ""+e.getMessage());
        }

        return true;
    }
}

Happy coding!

The null pointer exception is because when you create a new TransactionHistoryFragment using new onViewCreated is not called and hence transactionList is never initialized. You can create a setter for the list or pass it as a constructor to the fragment to fix this

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM