从另一个片段

时间:2017-01-06 04:07:06

标签: java android android-fragments dialog android-recyclerview

我有一个包含RecyclerView的Fragment。我正在尝试在RecyclerView上实现过滤器。过滤器UI将打开一个新的片段对话框,用户将在其中输入值。一旦用户点击片段对话框中的搜索按钮,该值应返回到RecyclerView片段,并且应清除视图中的现有数据。我想用我将从服务器获取的新数据集重新填充RecyclerView。我的问题是,我在RecyclerView Fragment中有一个名为resetAdapterDetails()的方法,如果从RecyclerView Fragment本身调用,它可以正常工作。但是,当我尝试从Fragment Dialog调用相同的方法时,我得到一个例外:

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

虽然数据在RecyclerView中仍然可见。

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;
    }
}

对话框片段

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());
            }
        });

    }
}

TransactionHistoryFragment(RecyclerView Fragment)中的fetchMobileNumber()方法是通过{strong> SearchMobileFragment(Dialog Fragment)fetchMobileNumber()方法调用的>。

我哪里错了?为什么transactionList.clear();抛出空指针异常?

3 个答案:

答案 0 :(得分:1)

您遇到此问题是因为您在SearchMobileFragment中创建了新的TransactionHistoryFragment实例search_button。这使得它的所有变量都为null并再次初始化它,这里你的transactionList变为空。

您也可以通过不同的方式轻松实现同样的目标。作为SearchogobileFragment作为DialogFragment的位置,您可以将其作为Activity并从TransactionHistoryFragment中将其作为startActivityForResult启动,并实现onActivityResult回调以进行fiteration。

但是现在你可以用不同的方式管理它:

第一种方式: 正如您在DialogFragment中所做的那样

search_button.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {

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

此处不要对fetchMobileNumber进行调用,在您的TransactionHistoryFragment的onResume中,您应该对此进行调用。点击search_button,将过滤数据保存到SharedPreferences,并在TransactionHistoryFragment的onResume中使用它进行过滤,之后从SharedPreferences onPause清除此保存的数据。

你应该删除

transactionList.clear(); 
来自TransactionHistoryFragment中的resetAdapterDetails()的代码

,因为在搜索过滤器之后,您将获得已经传递给适配器的更新的事务列表,然后强制不需要清除它。或者在清除它之前进行检查:

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

第二种方式:使用BroadcastReceiver可以实现同样的目的。 在TransactionHistoryFragment中注册一个接收者,从SearchMobileFragment注册sendBroadcast。在onHceive的TransactionHistoryFragment中执行过滤过程。

答案 1 :(得分:1)

我以不同的方式解决了上述问题。在对话框片段中,我实施了View.OnClickListener并创建了接口,以便从 RecyclerView Fragment 初始化相同内容。我在下面发布完整的源代码; 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);
    }
}

RecyclerView Fragment 修改:

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;
    }
}

快乐的编码!

答案 2 :(得分:0)

空指针异常是因为当您使用TransactionHistoryFragment new创建新onViewCreated时未调用,因此永远不会初始化transactionList。您可以为列表创建一个setter,或将其作为构造函数传递给片段以修复此