-2

I have added a filter for my searchview to show recyclerview items that match the query. The search seems to work but the app crashes if there are no items in recyclerview so can someone help me here a bit?

My fragment:

public class TextTypingTabFragment extends Fragment implements TabLayoutFragmentPagerAdapter.ITabLayoutIconFragmentPagerAdapter {
    private static final String TAG = TextTypingTabFragment.class.getSimpleName();

    private final TextTypingLoaderCallbacks mLoaderCallbacks = new TextTypingLoaderCallbacks();
    private TextTypingCustomAdapter mTextTypingCustomAdapter;

    private View mView;
    private ProgressBar mProgressBar;
    private ScrollView mScrollView;
    private RecyclerView mRecyclerView;

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

    // ----

    private Context getContextNonNull() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            return Objects.requireNonNull(getContext());
        } else {
            return getContext();
        }
    }

    // ----

    private int mItemCount = -1;
    private int mFirstVisibleItemPosition = -1, mFirstCompletelyVisibleItemPosition = -1;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LogUtil.d(TAG, "Fragment create");

        Bundle bundle = new Bundle();
        bundle.putString(AppEnvr.EXTRA_PACKAGE_NAME_KEY, MainActivity.sSelectedPackageName);

        getLoaderManager().initLoader(1, bundle, mLoaderCallbacks); // Init with 1

        setHasOptionsMenu(true);
        // ----

        LocalBroadcastManager.getInstance(getContextNonNull()).registerReceiver(mSelectedPackageNameChangedCustomReceiver, new IntentFilter(AppEnvr.ACTION_SELECTED_PACKAGE_NAME_CHANGED));
    }

    @Override
    public void onResume() {
        super.onResume();
        LogUtil.d(TAG, "Fragment resume");

        Bundle bundle = new Bundle();
        bundle.putString(AppEnvr.EXTRA_PACKAGE_NAME_KEY, MainActivity.sSelectedPackageName);

        getLoaderManager().restartLoader(1, bundle, mLoaderCallbacks); // Restart with 1
    }

    @Override
    public void onPause() {
        super.onPause();
        LogUtil.d(TAG, "Fragment pause");

        if (mTextTypingCustomAdapter != null) {
            mItemCount = mTextTypingCustomAdapter.getItemCount();
        }

        if (mRecyclerView != null) {
            LinearLayoutManager linearLayoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();

            if (linearLayoutManager != null) {
                mFirstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
                mFirstCompletelyVisibleItemPosition = linearLayoutManager.findFirstCompletelyVisibleItemPosition();
            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        LogUtil.d(TAG, "Fragment destroy");

        LocalBroadcastManager.getInstance(getContextNonNull()).unregisterReceiver(mSelectedPackageNameChangedCustomReceiver);
    }

    // ----

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        return inflater.inflate(R.layout.fragment_text_typing_tab, container, false);
    }

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

        mView = view;
        mProgressBar = view.findViewById(R.id.fragment_text_typing_tab_progress_bar);
        mScrollView = view.findViewById(R.id.fragment_text_typing_tab_scroll_view);
        mRecyclerView = view.findViewById(R.id.fragment_text_typing_tab_recycler_view);
    }

    // ----

    @Override
    public Fragment getItem() {
        return this;
    }

    @Override
    public CharSequence getPageTitle() {
        return "History";
    }

    @Override
    public int getIcon() {
        return R.drawable.ic_typesave;
    }

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

        final SearchView searchView = new SearchView(getActivity());
        searchView.setQuery(null, true);
        searchView.setQueryHint("Search");
        EditText searchEditText = searchView.findViewById(androidx.appcompat.R.id.search_src_text);
        searchEditText.setTextColor(getResources().getColor(R.color.white));
        searchEditText.setHintTextColor(getResources().getColor(R.color.tabTextColor));

        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                Filter filter = mTextTypingCustomAdapter.getFilter();

                if (filter != null) {
                    filter.filter(s);

                    return true;
                }

                return false;
            }

            @Override
            public boolean onQueryTextChange(String s) {
                Filter filter = mTextTypingCustomAdapter.getFilter();

                if (filter != null) {
                    filter.filter(s);

                    return true;
                }

                return false;
            }
        });

        menu.findItem(R.id.action_search).setActionView(searchView);

    }

    // ----

    private final BroadcastReceiver mSelectedPackageNameChangedCustomReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            LogUtil.d(TAG, "Receiver receive");

            // ----

            if (context == null || intent == null) {
                if (context == null) {
                    LogUtil.w(TAG, "Receiver receive: Context lack");
                }

                if (intent == null) {
                    LogUtil.w(TAG, "Receiver receive: Intent lack");
                }

                return;
            }

            // ----

            String intentAction = null;
            try {
                intentAction = intent.getAction();
            } catch (Exception e) {
                LogUtil.e(TAG, e.getMessage());
                LogUtil.e(TAG, e.toString());

                e.printStackTrace();
            }

            if (intentAction == null || !intentAction.equals(AppEnvr.ACTION_SELECTED_PACKAGE_NAME_CHANGED)) {
                if (intentAction == null) {
                    LogUtil.w(TAG, "Receiver receive: Intent action lack");
                } else if (!intentAction.equals(AppEnvr.ACTION_SELECTED_PACKAGE_NAME_CHANGED)) {
                    LogUtil.w(TAG, "Receiver receive: Intent action mismatch");
                }

                return;
            }

            // ----

            LogUtil.d(TAG, "Receiver receive: OK");

            // ----

            Bundle extras = null;
            try {
                extras = intent.getExtras();
            } catch (Exception e) {
                LogUtil.e(TAG, e.getMessage());
                LogUtil.e(TAG, e.toString());

                e.printStackTrace();
            }

            if (extras != null) {
                if (extras.containsKey(AppEnvr.EXTRA_PACKAGE_NAME_KEY)) {
                    String packageName = extras.getString(AppEnvr.EXTRA_PACKAGE_NAME_KEY, null);

                    // ----

                    Bundle bundle = new Bundle();
                    bundle.putString(AppEnvr.EXTRA_PACKAGE_NAME_KEY, packageName);

                    getLoaderManager().restartLoader(1, bundle, mLoaderCallbacks); // Restart with 1
                }
            }
        }
    };

    // ----

    private final class TextTypingLoaderCallbacks implements LoaderManager.LoaderCallbacks<ArrayList<TextTypingObject>> {
        private String mPackageName = null;

        @NonNull
        @Override
        public Loader<ArrayList<TextTypingObject>> onCreateLoader(int i, @Nullable Bundle bundle) {
            if (mScrollView != null) {
                mScrollView.setVisibility(View.GONE);
            }

            if (mRecyclerView != null) {
                mRecyclerView.setVisibility(View.GONE);
            }

            if (mProgressBar != null) {
                mProgressBar.setVisibility(View.VISIBLE);
            }

            // ----

            if (bundle != null) {
                mPackageName = bundle.getString(AppEnvr.EXTRA_PACKAGE_NAME_KEY, null);
            }

            // ----

            return new TextTypingLoader(getContextNonNull(), mPackageName);
        }

        @Override
        public void onLoadFinished(@NonNull Loader<ArrayList<TextTypingObject>> loader, @Nullable ArrayList<TextTypingObject> textTypingObjectArrayList) {
            if (textTypingObjectArrayList != null && !textTypingObjectArrayList.isEmpty()) {
                mTextTypingCustomAdapter = new TextTypingCustomAdapter(getContextNonNull(), textTypingObjectArrayList);
            } else {
                if (mTextTypingCustomAdapter != null) {
                    mTextTypingCustomAdapter = null;
                }

                // ----

                if (mPackageName != null && MainActivity.sSelectedPackageName != null) {
                    mPackageName = null;
                    MainActivity.sSelectedPackageName = null;

                    getLoaderManager().restartLoader(1, null, mLoaderCallbacks); // Restart with 1

                    return;
                }
            }

            // ----

            if (mProgressBar != null) {
                mProgressBar.setVisibility(View.GONE);
            }

            if (mTextTypingCustomAdapter != null) {
                if (mRecyclerView != null) {
                    int scrollToPosition = -1;

                    // ----

                    if (mItemCount != -1 && mFirstVisibleItemPosition != -1) {
                        int newItemCount = mTextTypingCustomAdapter.getItemCount();

                        // ----

                        if (newItemCount == mItemCount) { // No added/removed events
                            scrollToPosition = mFirstVisibleItemPosition;
                        } else if (newItemCount > mItemCount) { // Added events found
                            if (mFirstVisibleItemPosition != 0) {
                                int addedEventsCount = newItemCount - mItemCount;

                                scrollToPosition = mFirstVisibleItemPosition + addedEventsCount;

                                // ----

                                if (addedEventsCount >= 1 && mFirstVisibleItemPosition >= 1) {
                                    Snackbar snackbar = Snackbar.make(mView, getContextNonNull().getString(R.string.new_events_found, addedEventsCount) + " (text typing)", Snackbar.LENGTH_SHORT);
                                    snackbar.setAction(getContextNonNull().getString(R.string.scroll), v -> mRecyclerView.smoothScrollToPosition(0));
                                    snackbar.show();
                                }
                            }
                        } else /*if (newItemCount < mItemCount)*/ { // Removed events found
                            scrollToPosition = mFirstVisibleItemPosition;
                        }

                        // ----

                        mFirstVisibleItemPosition = -1;
                        mItemCount = -1;
                    }

                    // ----

                    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(mRecyclerView.getContext());
                    linearLayoutManager.setOrientation(RecyclerView.VERTICAL);
                    if (scrollToPosition != -1) {
                        linearLayoutManager.scrollToPosition(scrollToPosition);
                    }

                    mRecyclerView.setLayoutManager(linearLayoutManager);
                    mRecyclerView.setItemAnimator(new DefaultItemAnimator());
                    mRecyclerView.setAdapter(mTextTypingCustomAdapter);

                    // ----

                    mRecyclerView.setVisibility(View.VISIBLE);

                    // ----
                }
            } else {
                if (mScrollView != null) {
                    mScrollView.setVisibility(View.VISIBLE);
                }
            }

            // ----

            if (mPackageName != null) {
                mPackageName = null;
            }
        }

        @Override
        public void onLoaderReset(@NonNull Loader loader) {
        }
    }
}

SearchView Code:

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

        final SearchView searchView = new SearchView(getActivity());
        searchView.setQuery(null, true);
        searchView.setQueryHint("Search");
        EditText searchEditText = searchView.findViewById(androidx.appcompat.R.id.search_src_text);
        searchEditText.setTextColor(getResources().getColor(R.color.white));
        searchEditText.setHintTextColor(getResources().getColor(R.color.tabTextColor));

        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                Filter filter = mTextTypingCustomAdapter.getFilter();

                if (filter != null) {
                    filter.filter(s);

                    return true;
                }

                return false;
            }

            @Override
            public boolean onQueryTextChange(String s) {
                Filter filter = mTextTypingCustomAdapter.getFilter();

                if (filter != null) {
                    filter.filter(s);

                    return true;
                }

                return false;
            }
        });

        menu.findItem(R.id.action_search).setActionView(searchView);

    }

Error Log: Attempt to invoke virtual method 'android.widget.Filter com.app.app.adapter.TextTypingCustomAdapter.getFilter()' on a null object reference

Steven Rõgrê
  • 165
  • 1
  • 13

1 Answers1

3

When you are going to filter like this

Filter filter = mTextTypingCustomAdapter.getFilter();

if not match with any item.then your variable mTextTypingCustomAdapter is null. you should check null safety before filtering in both methods( onQueryTextSubmit() && onQueryTextChange() )

if(mTextTypingCustomAdapter != null){
Filter filter = mTextTypingCustomAdapter.getFilter();}