简体   繁体   English

从另一个片段重置RecyclerView适配器

[英]Reset RecyclerView adapter from another Fragment

I have a Fragment that contains a RecyclerView. 我有一个包含RecyclerView的Fragment。 I am trying to implement a filter on the RecyclerView. 我正在尝试在RecyclerView上实现过滤器。 The filter UI opens a new Fragment Dialog where the user will input a value. 过滤器UI将打开一个新的片段对话框,用户将在其中输入值。 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. 一旦用户点击片段对话框中的搜索按钮 ,该值应返回到RecyclerView片段,并且应清除视图中的现有数据。 I want to re-populate the RecyclerView with the new set of data that I will obtain from the server. 我想用我将从服务器获取的新数据集重新填充RecyclerView。 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. 我的问题是,我在RecyclerView Fragment中有一个名为resetAdapterDetails()的方法,如果从RecyclerView Fragment本身调用,它会按预期工作。 But, when I try to call the same method from the Fragment Dialog, I get an exception: 但是,当我尝试从Fragment Dialog调用相同的方法时,我得到一个例外:

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

Though the data is still visible in the RecyclerView. 虽然数据在RecyclerView中仍然可见。

The RecyclerView Fragment : RecyclerView片段

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) . 所述fetchMobileNumber()TransactionHistoryFragment(RecyclerView片段)的方法是通过称为fetchMobileNumber()其从所述SearchMobileFragment(对话片段)调用的方法。

Where am I going wrong? 我哪里错了? Why the transactionList.clear(); 为什么是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. 您收到此问题是因为您在SearchMobileFragment中创建了新的TransactionHistoryFragment实例search_button。 Which makes it's all variables null and initialize it again and here your transactionList becomes null. 这使得它的所有变量都为null并再次初始化它,这里您的transactionList变为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. 作为SearchogobileFragment作为DialogFragment的位置,您可以将其作为Activity并从TransactionHistoryFragment中将其作为startActivityForResult启动,并实现onActivityResult回调以进行fiteration。

But right now in your case you can manage it in different ways also: 但是现在你可以用不同的方式管理它:

First way: As you are doing in your DialogFragment 第一种方式:正如您在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. 不要在这里调用fetchMobileNumber,在您的TransactionHistoryFragment的onResume中,您应该调用它。 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. 在单击search_button时,将过滤器数据保存到SharedPreferences,并在TransactionHistoryFragment的onResume中使用它进行过滤,然后在此片段的SharedPreferences onPause中清除此保存的数据。

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. 来自TransactionHistoryFragment中的resetAdapterDetails()的代码,因为在搜索过滤器之后,您将获得更新的事务列表,该事务列表已经传递给适配器,然后强制不需要清除它。 Or have a check before clearing it like: 或者在清除它之前进行检查:

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

Second way: Using BroadcastReceiver you can achieve the same thing. 第二种方式:使用BroadcastReceiver可以实现同样的目的。 Register a receiver in your TransactionHistoryFragment and sendBroadcast from SearchMobileFragment. 在TransactionHistoryFragment中注册一个接收者,从SearchMobileFragment注册sendBroadcast。 In onReceive of the TransactionHistoryFragment do the filtration process. 在onHceive的TransactionHistoryFragment中执行过滤过程。

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 . Dialog Fragment中,我实现了一个View.OnClickListener并创建了一个Interface来从RecyclerView Fragment初始化它。 I am posting the complete source codes below; 我在下面发布完整的源代码; the SearchMobileFragment now looks like: SearchMobileFragment现在看起来像:

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: RecyclerView片段修改:

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. 空指针异常是因为当您使用new onViewCreated创建新的TransactionHistoryFragment未调用,因此transactionList永远不会被初始化。 You can create a setter for the list or pass it as a constructor to the fragment to fix this 您可以为列表创建一个setter,或将其作为构造函数传递给片段以解决此问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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