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