RecyclerView.Adapter onClick - android

I am having trouble implementing view.OnClickListener in my RecyclerView.Adapter. I am trying to implement multi-pane layout (landscape tablet layout version with RecyclerView and detail side by side). I have so far created this Activity:
public class MovieListActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_list);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
MovieListFragment movieListFragment = new MovieListFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.recycler_view_fragment, movieListFragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
which starts a Fragment:
public class MovieListFragment extends Fragment {
#BindView(R.id.recyclerView)
RecyclerView mRecyclerView;
private MoviesAdapter mAdapter;
public MovieListFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new MoviesAdapter(getContext());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_movie_list, container, false);
ButterKnife.bind(this,view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mRecyclerView.setAdapter(mAdapter);
return view;
}
#Override
public void onStart() {
super.onStart();
getPopularMovies();
}
private void getPopularMovies() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://api.themoviedb.org")
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
MoviesApiService service = restAdapter.create(MoviesApiService.class);
service.getPopularMovies(new Callback<Movie.MovieResult>() {
#Override
public void success(Movie.MovieResult movieResult, Response response) {
mAdapter.setMovieList(movieResult.getResults());
}
#Override
public void failure(RetrofitError error) { error.printStackTrace(); }
});
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
}
}
which calls the RecyclerView.Adapter:
public class MoviesAdapter extends RecyclerView.Adapter<MovieViewHolder> {
private List<Movie> mMovieList;
private LayoutInflater mInflater;
private Context mContext;
public MoviesAdapter(Context context) {
this.mContext = context;
this.mInflater = LayoutInflater.from(context); //
}
#Override
public MovieViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {
View view = mInflater.inflate(R.layout.movie_row_item, parent, false);
final MovieViewHolder viewHolder = new MovieViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int position = viewHolder.getAdapterPosition();
Intent intent = new Intent(mContext, MovieDetailActivity.class);
intent.putExtra(MovieDetailActivity.MOVIE_EXTRA, mMovieList.get(position));
mContext.startActivity(intent);
}
});
return viewHolder;
}
#Override
public void onBindViewHolder(MovieViewHolder holder, int position) {
Movie movie = mMovieList.get(position);
Picasso.with(mContext)
.load(movie.getPoster())
.placeholder(R.color.colorAccent)
.into(holder.thumbnail);
holder.movieTitle.setText(movie.getTitle());
holder.rating.setText(movie.getRating());
}
#Override
public int getItemCount() {
return (mMovieList == null) ? 0 : mMovieList.size();
}
public void setMovieList(List<Movie> movieList) {
this.mMovieList = new ArrayList<>();
this.mMovieList.addAll(movieList);
notifyDataSetChanged();
}
}
Here in onClick I need to decide whether to start a new Activity (like in my code) or update content of detail Fragment (in my tablet landscape layout).
According to this link, you should decide based on fact if your DetailFragment is != null in activity like this:
public void onItemSelected(int position) {
DisplayFragment displayFrag = (DisplayFragment) getFragmentManager()
.findFragmentById(R.id.display_frag);
if (displayFrag == null) {
// DisplayFragment (Fragment B) is not in the layout (handset layout),
// so start DisplayActivity (Activity B)
// and pass it the info about the selected item
Intent intent = new Intent(this, DisplayActivity.class);
intent.putExtra("position", position);
startActivity(intent);
} else {
// DisplayFragment (Fragment B) is in the layout (tablet layout),
// so tell the fragment to update
displayFrag.updateContent(position);
}
}
But I'm not able to check this in Adapter. Any help would be highly appreciated!
Thank you.

Created the custom interface click action to get the control in fragment class
i hope it will works for you
public class MoviesAdapter extends RecyclerView.Adapter {
MoviesAdapterCallback moviesAdapterCallback;
private List<Movie> mMovieList;
private LayoutInflater mInflater;
private Context mContext;
public MoviesAdapter(Context context,MoviesAdapterCallback moviesAdapterCallback) {
this.mContext = context;
this.moviesAdapterCallback =moviesAdapterCallback;
this.mInflater = LayoutInflater.from(context); //
}
#Override
public MovieViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {
View view = mInflater.inflate(R.layout.movie_row_item, parent, false);
final MovieViewHolder viewHolder = new MovieViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
/* int position = viewHolder.getAdapterPosition();
Intent intent = new Intent(mContext, MovieDetailActivity.class);
intent.putExtra(MovieDetailActivity.MOVIE_EXTRA, mMovieList.get(position));
mContext.startActivity(intent);
*/ moviesAdapterCallback.MovieClicked(view);
}
});
return viewHolder;
}
#Override
public void onBindViewHolder(MovieViewHolder holder, int position) {
Movie movie = mMovieList.get(position);
Picasso.with(mContext)
.load(movie.getPoster())
.placeholder(R.color.colorAccent)
.into(holder.thumbnail);
holder.movieTitle.setText(movie.getTitle());
holder.rating.setText(movie.getRating());
}
#Override
public int getItemCount() {
return (mMovieList == null) ? 0 : mMovieList.size();
}
public void setMovieList(List<Movie> movieList) {
this.mMovieList = new ArrayList<>();
this.mMovieList.addAll(movieList);
notifyDataSetChanged();
}
public interface MoviesAdapterCallback {
void MovieClicked(View view);
}
}
in Fragment Class
public class MovieListFragment extends Fragment {
#BindView(R.id.recyclerView)
RecyclerView mRecyclerView;
private MoviesAdapter mAdapter;
public MovieListFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_movie_list, container, false);
ButterKnife.bind(this,view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mAdapter = new MoviesAdapter(getContext(), new MoviesAdapter.MoviesAdapterCallback(){
#Override
public void MovieClicked(View view) {
DisplayFragment displayFrag = (DisplayFragment) getFragmentManager()
.findFragmentById(R.id.display_frag);
if (displayFrag == null) {
// DisplayFragment (Fragment B) is not in the layout (handset layout),
// so start DisplayActivity (Activity B)
// and pass it the info about the selected item
Intent intent = new Intent(this, DisplayActivity.class);
intent.putExtra("position", position);
startActivity(intent);
} else {
// DisplayFragment (Fragment B) is in the layout (tablet layout),
// so tell the fragment to update
displayFrag.updateContent(position);
}
}
});
mRecyclerView.setAdapter(mAdapter);
return view;
}
#Override
public void onStart() {
super.onStart();
getPopularMovies();
}
private void getPopularMovies() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://api.themoviedb.org")
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
MoviesApiService service = restAdapter.create(MoviesApiService.class);
service.getPopularMovies(new Callback<Movie.MovieResult>() {
#Override
public void success(Movie.MovieResult movieResult, Response response) {
mAdapter.setMovieList(movieResult.getResults());
}
#Override
public void failure(RetrofitError error) { error.printStackTrace(); }
});
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
}
}

Related

Android ViewPager2 RecyclerView notifyDataSetChanged() not working

I'm using ViewPager2 and RecyclerView develop to Search activity.
What I want is use text entered in EditText as request parameter and response data is reflected in the RecyclerView.
I checked that the data was responded normally, but it was not reflected in the view.
I read so many questions and posts, but I couldn't solve the problem that the view was not refreshed.
Upon checking, data was added to the list of RecyclerView, the methods of the RecyclerView Adapter were not executed at all.
SearchActivity
public class SearchActivity extends AppCompatActivity {
private ActivitySearchBinding binding;
private static final int[] TAB_TITLES = new int[]{R.string.tab_text_1, R.string.tab_text_2};
private final String key;
private BusStopInterface busStopInterface;
private PlaceholderFragment fragment;
private SectionsPagerAdapter sectionsPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySearchBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
sectionsPagerAdapter = new SectionsPagerAdapter(SearchActivity.this);
ViewPager2 pager = binding.viewPager;
pager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = binding.tabs;
EditText searchBox = binding.searchBox;
fragment = new PlaceholderFragment();
new TabLayoutMediator(tabs, pager, (tab, position) -> tab.setText(TAB_TITLES[position])).attach();
RetrofitClient retrofitClient = RetrofitClient.getInstance();
busStopInterface = RetrofitClient.getRetrofitInterface();
searchBox.addTextChangedListener(textWatcher);
pager.registerOnPageChangeCallback(pageChangeCallback);
}
ViewPager2.OnPageChangeCallback pageChangeCallback = new ViewPager2.OnPageChangeCallback() {
#Override
public void onPageSelected(int position) {
super.onPageSelected(position);
if (position == 0) {
Log.d("position", "Bus stop");;
} else if (position == 1) {
Log.d("position", "Bus");;
}
}
};
TextWatcher textWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
busStopInterface.getBusStop(key, 25, "json", 25, s.toString()).enqueue(new Callback<Example>() {
#Override
public void onResponse(Call<Example> call, Response<Example> response) {
if (response.isSuccessful()) {
Example example = response.body();
Items items = example.getResult().getBody().getItems(); //I checked the data response.
fragment.resetRecyclerView(items.getItem());
sectionsPagerAdapter.notifyDataSetChanged();
Log.d("retrofit", "Data fetch success");
} else {
Log.d("retrofit", "Data fetch fail");
}
}
#Override
public void onFailure(Call<Example> call, Throwable t) {
Log.d("retrofit", t.getMessage());
}
});
}
};
}
PlaceholderFragment
public class PlaceholderFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
private PageViewModel pageViewModel;
private FragmentSearchBinding binding;
public List<BusStopItem> items = new ArrayList<>();
public SearchRecyclerViewAdapter adapter = new SearchRecyclerViewAdapter(items);
public static PlaceholderFragment newInstance(int index) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle bundle = new Bundle();
bundle.putInt(ARG_SECTION_NUMBER, index);
fragment.setArguments(bundle);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pageViewModel = new ViewModelProvider(this).get(PageViewModel.class);
int index = 1;
if (getArguments() != null) {
index = getArguments().getInt(ARG_SECTION_NUMBER);
}
pageViewModel.setIndex(index);
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentSearchBinding.inflate(inflater, container, false);
View root = binding.getRoot();
pageViewModel.getIndex().observe(getViewLifecycleOwner(), new Observer<Integer>() {
#Override
public void onChanged(Integer index) {
if (index == 1) {
adapter.setItemViewType(SearchRecyclerViewAdapter.VIEWTYPE_BUS_STOP);
} else if (index == 2) {
adapter.setItemViewType(SearchRecyclerViewAdapter.VIEWTYPE_BUS);
}
}
});
return root;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
RecyclerView recyclerView = binding.searchRecyclerView;
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), 1));
}
#Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
public void resetRecyclerView(List<BusStopItem> newItems) {
items.clear();
items.addAll(newItems);
adapter.notifyDataSetChanged();
}
}
SearchRecyclerViewAdapter
public class SearchRecyclerViewAdapter extends RecyclerView.Adapter<SearchRecyclerViewAdapter.ViewHolder> {
public static final int VIEWTYPE_BUS_STOP = 0;
public static final int VIEWTYPE_BUS = 1;
int mItemViewType;
List<BusStopItem> busStopItems;
public class ViewHolder extends RecyclerView.ViewHolder {
TextView busStopName, busStopId, busStopLocation, busName, busArea, busRoute;
public ViewHolder(#NonNull View itemView) {
super(itemView);
busStopName = itemView.findViewById(R.id.busStopName);
busStopId = itemView.findViewById(R.id.busStopId);
busStopLocation = itemView.findViewById(R.id.busStopLocation);
busName = itemView.findViewById(R.id.busName);
busArea = itemView.findViewById(R.id.busArea);
busRoute = itemView.findViewById(R.id.busRoute);
}
public void setBusStopItem(BusStopItem item) {
busStopName.setText(item.getNodenm());
if(item.getNodeno() != null) {
busStopId.setText(item.getNodeno().toString());
}
}
}
public SearchRecyclerViewAdapter(List<BusStopItem> busStopItems) {
this.busStopItems = busStopItems;
}
public void setItemViewType(int viewType) {
mItemViewType = viewType;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = null;
if (viewType == VIEWTYPE_BUS_STOP) {
view = inflater.inflate(R.layout.search_bus_stop_item, parent, false);
} else if (viewType == VIEWTYPE_BUS) {
view = inflater.inflate(R.layout.search_bus_item, parent, false);
}
SearchRecyclerViewAdapter.ViewHolder vh = new SearchRecyclerViewAdapter.ViewHolder(view);
return vh;
}
#Override
public int getItemViewType(int position) {
return mItemViewType;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
if (mItemViewType == VIEWTYPE_BUS_STOP) {
holder.setBusStopItem(busStopItems.get(position));
} else if (mItemViewType == VIEWTYPE_BUS) {
}
}
#Override
public int getItemCount() {
return busStopItems.size();
}
}
SectionsPagerAdapter
public class SectionsPagerAdapter extends FragmentStateAdapter {
public SectionsPagerAdapter(FragmentActivity fa) {
super(fa);
}
#NonNull
#Override
public Fragment createFragment(int position) {
return PlaceholderFragment.newInstance(position + 1);
}
#Override
public int getItemCount() {
return 2;
}
}
What I tried
public void resetRecyclerView(List<BusStopItem> newItems) {
items.clear();
items.addAll(newItems);
adapter.notifyDataSetChanged();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(this).attach(this).commit();
}
java.lang.NullPointerException: Attempt to invoke virtual method 'androidx.fragment.app.FragmentTransaction androidx.fragment.app.FragmentManager.beginTransaction()' on a null object reference
You create PlaceholderFragment but not add it to FragmmentManger.
fragment = new PlaceholderFragment();
When `busStopInterface.getBusStop()` get return, you set data to
private PlaceholderFragment fragment
and fragment is not attach to any Activity,so UI dosen't refresh. You should get PlaceholderFragment instance from SectionsPagerAdapter or create PlaceholderFragment instance for SectionsPagerAdapter, and you can set data to real PlaceholderFragment
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySearchBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
fragments = new ArrayList<>();
fragments.add(PlaceholderFragment.newInstance(1));
fragments.add(PlaceholderFragment.newInstance(2));
sectionsPagerAdapter = new SectionsPagerAdapter(SearchActivity.this, fragments);
ViewPager2 pager = binding.viewPager;
pager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = binding.tabs;
EditText searchBox = binding.searchBox;
new TabLayoutMediator(tabs, pager, (tab, position) -> tab.setText(TAB_TITLES[position])).attach();
RetrofitClient retrofitClient = RetrofitClient.getInstance();
busStopInterface = RetrofitClient.getRetrofitInterface();
searchBox.addTextChangedListener(textWatcher);
pager.registerOnPageChangeCallback(pageChangeCallback);
}
public class SectionsPagerAdapter extends FragmentStateAdapter {
private final List<PlaceholderFragment> fragments;
public SectionsPagerAdapter(FragmentActivity fa, List<PlaceholderFragment> fragments) {
super(fa);
this.fragments = fragments;
}
#NonNull
#Override
public Fragment createFragment(int position) {
return fragments.get(position);
}
#Override
public int getItemCount() {
return 2;
}
}
busStopInterface.getBusStop(key, 25, "json", 25, s.toString()).enqueue(new Callback<Example>() {
#Override
public void onResponse(Call<Example> call, Response<Example> response) {
if (response.isSuccessful()) {
Example example = response.body();
Items items = example.getResult().getBody().getItems(); //I checked the data response.
fragments.get(1).resetRecyclerView(items.getItem());
Log.d("retrofit", "Data fetch success");
} else {
Log.d("retrofit", "Data fetch fail");
}
}
#Override
public void onFailure(Call<Example> call, Throwable t) {
Log.d("retrofit", t.getMessage());
}
});
PS. remove
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(this).attach(this).commit();

Android fragment lifecycle added more items into List on pressing back button

As i'm using FragNav library i have some items into List and when i switching on other fragment and after pressing on BackButton i have some other items into this List,
for example generally i have 1 item into List with RecyclerView after switching on other fragment and pressing back button on phone i have 2 items into RecyclerView and using onSaveInstanceState,
onActivityCreated couldn't resolve my problem
my Fragment:
public class HomeFragment extends BaseFragment implements IAnimationListener, View.OnClickListener, InstagramFeedsAdapter.OnClickListener {
...
// constructor
public static HomeFragment createInstance(int instance) {
HomeFragment fragment = new HomeFragment();
Bundle bundle = new Bundle();
bundle.putInt(BaseFragment.ARGS_INSTANCE, instance);
fragment.setArguments(bundle);
return fragment;
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.instagram_post_container, container, false);
activity = getActivity();
context = getActivity().getBaseContext();
mediaUrls = new ArrayList<>();
feedsSchema = new FeedsSchema();
feedsSchema.setId(1);
mediaUrls.add("http://gizasystems.com/wp-content/uploads/2014/08/natural-world-hero3.jpg");
feedsSchema.setFeed_media_url(mediaUrls);
feedsSchema.setFollowers_count(10);
feedsSchema.setFollowings_count(20);
feedsSchema.setPage_name("my test");
feedsSchema.setType(FeedsSchema.feed_types.IMAGE);
items.add(feedsSchema);
instagram_feeds = mView.findViewById(R.id.instagram_feeds);
layoutManager = new LinearLayoutManager(context);
instagram_feeds.setLayoutManager(layoutManager);
instagram_feeds.setNestedScrollingEnabled(false);
instagramFeedsAdapter = new InstagramFeedsAdapter(activity, context, this, items);
return mView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Bundle arguments = getArguments();
}
#Override
public void onAnimationEnd() {
}
#Override
public void onClick(View view) {
int clickedItem = view.getId();
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onStop() {
super.onStop();
}
#Override
public void onItemClick(View view, String transitionName, int position) {
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList("someVarA", new ArrayList<>(items));
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null)
items = savedInstanceState.getParcelableArrayList("someVarA");
}
}
and my Adapter:
public class InstagramFeedsAdapter extends RecyclerView.Adapter<InstagramFeedsAdapter.InstagramFeedsViewHolder>
implements PreviewView.OnPreviewChangeListener {
private OnClickListener listener;
private List<FeedsSchema> feedsItems;
private Context context;
private boolean hoveredOnPopup = false;
private ExoPlayerManager exoPlayerManager;
private Activity activity;
private enum feedType {
IMAGE,
IMAGESLIDER,
VIDEO
}
public InstagramFeedsAdapter(Activity activity, Context context, OnClickListener listener, List<FeedsSchema> items) {
this.listener = listener;
this.feedsItems = items;
this.context = context;
this.activity = activity;
}
#Override
public void onBindViewHolder(#NonNull final InstagramFeedsViewHolder holder, int position) {
int feedType = feedsItems.get(position).getType().ordinal();
implementingGeneralViewData(holder, position);
if (feedType == 0) {
if (feedsItems.get(position).getFeed_media_url().size() > 1) {
implementingImageSliderView(holder, position);
} else {
implementingImageView(holder, position);
}
} else {
implementingVideoPlayerView(holder, position);
}
}
private void implementingVideoPlayerView(InstagramFeedsViewHolder holder, int position) {
}
#SuppressLint("CheckResult")
private void implementingImageSliderView(final InstagramFeedsViewHolder holder, final int position) {
}
#SuppressLint("CheckResult")
private void implementingImageView(final InstagramFeedsViewHolder holder, final int position) {
}
#Override
public int getItemCount() {
return feedsItems.size();
}
public class InstagramFeedsViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener, PopupInflaterListener, PopupStateListener, PopupOnHoverListener {
...
public InstagramFeedsViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
ButterKnife.bind(this, itemView);
}
#Override
public void onClick(View view) {
}
public void bind(int position) {
...
}
}

new value not inserted in my user interface when adding new object

I am trying to add an contact object and the way I do it is when the user hits add button in the menu bar; this is how I do it.
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.new_contact:
Contact contact = new Contact();
ContactLab.get(getActivity()).addContact(contact);
updateUI();
mCallbacks.onContactSelected(contact);
return true;
case R.id.action_edit:
return true;
case R.id.action_delete:
ContactLab crimeLab = ContactLab.get(getActivity());
crimeLab.deleteContact(mContact);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
I have the following fragment
public class ContactListFragment extends Fragment {
// private static final String SAVED_SUBTITLE_VISIBLE = "subtitle";
private static final String ARG_CRIME_ID = "crime_id";
private RecyclerView mCrimeRecyclerView;
private ContactAdapter mAdapter;
public Contact mContact;
private Callbacks mCallbacks;
/**
* Required interface for hosting activities.
*/
public interface Callbacks {
void onContactSelected(Contact contact);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
mCallbacks = (Callbacks) context;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_contact_list, container, false);
mCrimeRecyclerView = (RecyclerView) view
.findViewById(R.id.contact_recycler_view);
mCrimeRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
if (savedInstanceState != null) {
}
updateUI();
return view;
}
#Override
public void onResume() {
super.onResume();
updateUI();
}
#Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
private void updateSubtitle() {
ContactLab crimeLab = ContactLab.get(getActivity());
int contactCount = crimeLab.getContacts().size();
String subtitle = getString(R.string.subtitle_format, contactCount);
AppCompatActivity activity = (AppCompatActivity) getActivity();
activity.getSupportActionBar().setSubtitle(subtitle);
}
public void updateUI() {
ContactLab crimeLab = ContactLab.get(getActivity());
List<Contact> contacts = crimeLab.getContacts();
if (mAdapter == null) {
mAdapter = new ContactAdapter(contacts);
mCrimeRecyclerView.setAdapter(mAdapter);
} else {
mAdapter.setContacts(contacts);
mAdapter.notifyDataSetChanged();
}
updateSubtitle();
}
private class ContactHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
private TextView mTitleTextView;
public ContactHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater.inflate(R.layout.list_item_content, parent, false));
itemView.setOnClickListener(this);
mTitleTextView = (TextView) itemView.findViewById(R.id.content_name);
}
public void bind(Contact contact) {
mContact = contact;
mTitleTextView.setText(mContact.getName());
}
#Override
public void onClick(View view) {
mCallbacks.onContactSelected(mContact);
}
}
private class ContactAdapter extends RecyclerView.Adapter<ContactHolder> {
private List<Contact> mContacts;
public ContactAdapter(List<Contact> crimes) {
mContacts = crimes;
}
#Override
public ContactHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
return new ContactHolder(layoutInflater, parent);
}
#Override
public void onBindViewHolder(ContactHolder holder, int position) {
Contact contact=mContacts.get(position);
holder.bind(contact);
}
#Override
public int getItemCount() {
return mContacts.size();
}
public void setContacts(List<Contact> contacts) {
mContacts = contacts;
}
}
and then I start the above fragment from the following activity fragment
public class ContactListActivity extends SingleFragmentActivity
implements ContactListFragment.Callbacks, ContactFragment.Callbacks {
#Override
protected Fragment createFragment() {
return new ContactListFragment();
}
#Override
protected int getLayoutResId() {
return R.layout.activity_masterdetail;
}
#Override
public void onContactSelected(Contact contact) {
if (findViewById(R.id.detail_fragment_container) == null) {
Intent intent = ContactPagerActivity.newIntent(this, contact.getIDD());
startActivity(intent);
} else {
Fragment newDetail = ContactFragment.newInstance(contact.getId());
getSupportFragmentManager().beginTransaction()
.replace(R.id.detail_fragment_container, newDetail)
.commit();
}
}
public void onContactUpdated(Contact crime) {
ContactListFragment listFragment = (ContactListFragment)
getSupportFragmentManager()
.findFragmentById(R.id.fragment_container);
listFragment.updateUI();
}
}
could any one show me whre I am doing wrong because I see the followoig error in my log
Process: com.bignerdranch.android.adressbook, PID: 28871
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.bignerdranch.android.adressbook.Contact.getName()' on a null object reference
atcom.bignerdranch.android.adressbook.ContactFragment.onCreateView(ContactFragment.java:82)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2354)

RecyclerView.Adapter onClick ClassCastException

I'm trying to load a Fragment inside an Activity and I was able to load the items. Now, what I want to do is to click the items on the list and pass it to the DetailsView.class which is a Fragment that will receive the bundle data. But everytime I click on the item I always get an error. Below is the logcat error that I'm getting
Logcat Error
java.lang.ClassCastException: com.test.example.LoadAFragment cannot be cast to com.test.example.MainActivity at com.test.example.controller.DetailsView.onCreateView(DetailsView.java:178)
line java:178
MainActivity activity = ((MainActivity) getActivity());
LoadAFragment.class
public class LoadAFragment extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.load_layout);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
MyFragment myFragment = new MyFragment();
fragmentTransaction.add(R.id.frame_container, myFragment);
fragmentTransaction.commit();
}
}
RecyclerView Adapter
public class MyFragmentAdapter extends RecyclerView.Adapter <RecyclerView.ViewHolder> {
private List<ListModel> list;
private Context mContext = null;
private DetailsView detailsView;
public MyFragmentAdapter(Context context, List<ListModel> list) {
mContext = context;
this.list = list;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
final ListModel list = list.get(holder.getAdapterPosition());
String mID = list.getID();
final int id = Integer.valueOf(mID );
((MyViewHolder) holder).title.setText(list.getTitle());
((MyViewHolder) holder).caption.setText(list.getCaption());
((MyViewHolder) holder).itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager manager = ((Activity) mContext).getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Bundle bundle = new Bundle();
bundle.putInt("id", id);
detailsView = new DetailsView ();
detailsView.setTitle(title);
detailsView.setArguments(bundle);
transaction.replace(R.id.frame_container, detailsView);
transaction.addToBackStack("list");
transaction.commit();
}
});
}
#Override
public int getItemCount() {
return (list != null? list.size():0);
}
private class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public TextView caption;
MyViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
caption = (TextView) itemView.findViewById(R.id.caption );
}
}
}
MyFragment.class
public class MyFragment extends Fragment{
List<ListModel> list;
RecyclerView mRecyclerView;
MyFragmentAdapter myFragmentAdapter;
ListDb listDb;
public MyFragment() {}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View rootView = inflater.inflate(R.layout.fragment, container, false);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview);
listDb = new ListDb(getActivity());
list = listDb.getList();
myFragmentAdapter = new MyFragmentAdapter (getActivity(), list);
mRecyclerView.setAdapter(myFragmentAdapter);
return rootView;
}
}
DetailsView.class
public class DetailsView extends Fragment{
private MainActivity activity;
Bundle b;
public DetailsView() {}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
b = savedInstanceState.getBundle("save");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
activity = ((MainActivity) getActivity());
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);}
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (b != null) {
setTitle(b.getString("title"));
id = b.getInt("id");
}
if (b != this.getArguments().getInt("id")) {
b = this.getArguments().getInt("id");
//get data from id
}
}
}
The best and cleanest solution would be to pass a listener to the adapter.
public interface MyClickListener {
void onResult(Data data);
}
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public MyAdapter(Context context, MyClickListener listener, List<ListModel> list) {
mContext = context;
this.list = list;
this.listener = listener;
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
Data data = getData(position);
//bind views
holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onResult(data);
}
});
}
}
Have the Fragment implement the listener and create the new adapter.
public class MyFragment extends Fragment implements MyClickListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyAdapter adapter = new MyAdapter(getActivity(),this,listData);
}
#Override
public void onResult(Data data) {
//do work after an item is clicked
}
}
Cast getActivity() to 'LoadAFragment' instead of 'MainActivity' in DetailsView.java. This way:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
activity = ((LoadAFragment) getActivity());
return rootView;
}
try this way to get Reference of MainActivity in your DetailViewFragment
private MainActivity parent_activity;
#Override
public void onAttach(Activity activity)
{
parent_activity = (MainActivity.class.isAssignableFrom(activity
.getClass())) ? (MainActivity) activity : null;
super.onAttach(activity);
}
#Override
public void onDetach()
{
parent_activity = null;
super.onDetach();
}
Now use the reference using:
if(parent_activity!=null)
{
parent_activity.someMethod();
}

Update the row item data of recyclerview

The fragment consists of View Pager which shows the product count that
needs to be updated when the product is deleted or added .
public class SubCategoryFragment extends BaseFragment implements OnItemClickListener
{
private View rootView;
private MasterCategory subCategory;
private RecyclerView subCategoryRecyclerView;
private SubCategoryListAdapter subCategoryListAdapter;
private ArrayList<MasterCategory> superSubCategories;
private String iconImageURL;
private ArrayList<MerchantOrder> merchantorder;
/*private IRequestComplete iRequestComplete;*/
private int categoryId;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
super.onCreateView(inflater, container, savedInstanceState);
return rootView = inflater.inflate(R.layout.fragment_category_list, container, false);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
initialiseUI();
}
initialise fragment
protected void initialiseUI()
{
categoryId = getArguments().getInt("categoryId");
iconImageURL = (String) getArguments().getSerializable("iconImageURL");
subCategory = (MasterCategory) getArguments().getSerializable("data");
subCategoryRecyclerView = (RecyclerView) rootView.findViewById(R.id.category_list_rc_view);
rootView.findViewById(R.id.dashboard_progressbar_newlyadded).setVisibility(View.GONE);
subCategoryRecyclerView.setHasFixedSize(true);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(context);
subCategoryRecyclerView.setLayoutManager(mLayoutManager);
superSubCategories = subCategory.getCategories();
rootView.findViewById(R.id.dashboard_progressbar_newlyadded).setVisibility(View.GONE);
if (superSubCategories != null && !superSubCategories.isEmpty())
{
subCategoryListAdapter = new SubCategoryListAdapter(superSubCategories, iconImageURL);
subCategoryRecyclerView.setAdapter(subCategoryListAdapter);
subCategoryListAdapter.setmOnItemClickListener(this);
updateListView();
}
else
{
rootView.findViewById(R.id.text_no_order_error).setVisibility(View.VISIBLE);
((TextView) rootView.findViewById(R.id.text_no_order_error)).setText("No Category found!");
}
}
Update the listview
private void updateListView()
{
if (subCategoryListAdapter == null)
{
subCategoryListAdapter = new SubCategoryListAdapter(superSubCategories,iconImageURL);
subCategoryRecyclerView.setAdapter(subCategoryListAdapter);
}
else
{
subCategoryListAdapter.notifyDataSetChanged();
}
subCategoryListAdapter.notifyDataSetChanged();
}
the itemclick opens up a fragment which displays the product details
#Override
public void onItemClick(View view, int position)
{
/*MasterCategory superSubCategories = subCategoryListAdapter.getSuperSubCategory(position);
Bundle bundle = new Bundle();
bundle.putSerializable("data", superSubCategories);
SuperSubCategoryProductsFragment superSubCategoryProductsFragment = new SuperSubCategoryProductsFragment();
superSubCategoryProductsFragment.setArguments(bundle);
manageFragment(superSubCategoryProductsFragment, SuperSubCategoryProductsFragment.class.getName(), CategoryDetailsFragment.class.getName(), bundle);*/
/*ArrayList<MasterCategory> superSubCategories = subCategoryListAdapter.getSuperSubCategory(position).getCategories();
if (null != superSubCategories){
Bundle bundle = new Bundle();
bundle.putSerializable("data", superSubCategories);
SuperSubCategoryListFragment categoryDetailsFragment = new SuperSubCategoryListFragment();
categoryDetailsFragment.setArguments(bundle);
manageFragment(categoryDetailsFragment, SuperSubCategoryListFragment.class.getName(), SubCategoryFragment.class.getName(), null);
}*/
MasterCategory superSubCategories = subCategoryListAdapter.getSuperSubCategory(position);
superSubCategories.getSubCategoryCount();
superSubCategories.getProductCount();
subCategoryListAdapter.notifyDataSetChanged();
if (superSubCategories.isHasChildCategory())
{
Bundle bundle = new Bundle();
bundle.putSerializable("data", superSubCategories);
Intent intent = new Intent(context, BaseFragmentActivity.class);
intent.putExtra("toolbarTitle", superSubCategories.getName());
intent.putExtra("FragmentClassName", SuperSubCategoryFragment.class.getName());
intent.putExtra("data", bundle);
startActivity(intent);
}
else
{
Intent intent = new Intent(context, BaseFragmentActivity.class);
Bundle bundle = new Bundle();
bundle.putInt("categoryId", superSubCategories.getCategoryId());
bundle.putString("categoryName", superSubCategories.getName());
bundle.putBoolean("isSubCatProducts", !superSubCategories.isHasChildCategory());
bundle.putInt("ProductCount", superSubCategories.getProductCount());
intent.putExtra("toolbarTitle", superSubCategories.getName());
intent.putExtra("FragmentClassName", SubCategoryProductsFragment.class.getName());
intent.putExtra("data", bundle);
startActivity(intent);
}
}
#Override
public void onPause()
{
super.onPause();
}
#Override
public void onResume()
{
super.onResume();
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView)
{
super.onAttachedToRecyclerView(subCategoryRecyclerView);
subCategoryRecyclerView.getAdapter().notifyDataSetChanged();
}
}
This is my Adapter attached to the fragment
public class SubCategoryListAdapter extends RecyclerView.Adapter<SubCategoryListAdapter.ViewHolder> implements View.OnClickListener {
private static final String TAG = SubCategoryListAdapter.class.getSimpleName();
private ArrayList<MasterCategory> superSubCategories;
private ImageLoader imageloader;
private com.amoda.androidlib.intf.OnItemClickListener mOnItemClickListener;
private String iconImageURL;
#Override
public void onClick(View view)
{
if (mOnItemClickListener != null)
mOnItemClickListener.onItemClick(view, (Integer) view.getTag());
}
public class ViewHolder extends RecyclerView.ViewHolder
{
public TextView name;
public TextView productCount;
public NetworkImageView image;
public ViewHolder(View itemLayoutView)
{
super(itemLayoutView);
productCount = (TextView) itemLayoutView.findViewById(R.id.product_count);
name = (TextView) itemLayoutView.findViewById(R.id.name);
image = (NetworkImageView) itemLayoutView.findViewById(R.id.image);
}
}
public SubCategoryListAdapter(ArrayList<MasterCategory> superSubCategories, String iconImageURL)
{
this.superSubCategories = superSubCategories;
imageloader = Global.getInstance().getImageLoader();
this.iconImageURL = iconImageURL;
}
#Override
public SubCategoryListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.super_category_list_row, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position)
{
holder.name.setText("" + superSubCategories.get(position).getName());
holder.image.setDefaultImageResId(R.drawable.logo_amoda);
holder.image.setImageUrl(iconImageURL, imageloader);
if(!superSubCategories.get(position).isHasChildCategory())
{
holder.productCount.setText("" + superSubCategories.get(position).getProductCount());
}
else
{
holder.productCount.setText("");
holder.productCount.setBackgroundResource(R.drawable.icn_right_arrow);
}
holder.itemView.setTag(position);
holder.itemView.setOnClickListener(this);
}
public void setmOnItemClickListener(com.amoda.androidlib.intf.OnItemClickListener mOnItemClickListener)
{
this.mOnItemClickListener = mOnItemClickListener;
}
#Override
public int getItemCount()
{
if (superSubCategories != null)
return superSubCategories.size();
else
return 0;
}
public MasterCategory getSuperSubCategory(int position)
{
return superSubCategories.get(position);
}
}
This is my View pager in my activity
private void showSubCategoryTabs()
{
setToolbarTitle(category != null ? category.getName() : "");
try
{
mPromotionalImage.setDefaultImageResId(R.drawable.nodeals_img);
mPromotionalImage.setImageUrl(category.getImageUrl(), imageLoader);
}
catch (Exception e)
{
e.printStackTrace();
}
tabContent = new ArrayList<String>();
for (MasterCategory subCategories : category.getCategories())
{
/*Check if the sub-sub category has super-sub category or not.*/
if (null != subCategories.getCategories())
tabContent.add(subCategories.getName());
}
mViewPager.setAdapter(mSectionsPagerAdapter);
final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
}
#Override
public void onPageSelected(int position)
{
Fragment fragment = ((SectionsPagerAdapter) mViewPager.getAdapter()).getFragment(position);
if (fragment != null)
{
fragment.onResume();
}
}
#Override
public void onPageScrollStateChanged(int state)
{
}
});
}
public class SectionsPagerAdapter extends FragmentStatePagerAdapter
{
private SectionsPagerAdapter sectionspageradapter;
private FragmentManager fragmentManager=null;
private Bundle bundle=new Bundle();
public SectionsPagerAdapter(FragmentManager fm)
{
super(fm);
fragmentManager=fm;
}
#Override
public Object instantiateItem(ViewGroup container,int position)
{
Object obj=super.instantiateItem(container,position);
if(obj instanceof Fragment)
{
Fragment f=(Fragment)obj;
String tag=f.getTag();
f.onResume();
}
return obj;
}
#Override
public Fragment getItem(int position)
{
MasterCategory subCategories = category.getCategories().get(position);
if (subCategories.isHasChildCategory())
{
SubCategoryFragment subCategoryFragment = new SubCategoryFragment();
Bundle bundle = new Bundle();
bundle.putSerializable("iconImageURL", category.getIconImageUrl());
bundle.putSerializable("data", category.getCategories().get(position));
subCategoryFragment.setArguments(bundle);
return subCategoryFragment;
}
else
{
SubCategoryProductsFragment subCategoryProductsFragment = new SubCategoryProductsFragment();
Bundle bundle = new Bundle();
bundle.putInt("categoryId", subCategories.getCategoryId());
bundle.putString("categoryName", subCategories.getName());
bundle.putBoolean("isSubCatProducts", true);
subCategoryProductsFragment.setArguments(bundle);
return subCategoryProductsFragment;
}
}
#Override
public int getCount()
{
return tabContent.size();
}
#Override
public CharSequence getPageTitle(int position)
{
Locale l = Locale.getDefault();
return tabContent.get(position);
}
public Fragment getFragment(int position)
{
String tag = String.valueOf(mMerchantSubCategories.get(position));
return fragmentManager.findFragmentByTag(tag);
}
}
#Override
public void onResume()
{
if (!EventBus.getDefault().isRegistered(this))
EventBus.getDefault().register(this);
super.onResume();
}
#Override
protected void onPause()
{
super.onPause();
}
#Override
public void onStop()
{
super.onStop();
//*Unregister event bus when the app goes in background*//*
if (EventBus.getDefault().isRegistered(this))
EventBus.getDefault().unregister(this);
}
#Override
public void onDestroy()
{
super.onDestroy();
if (EventBus.getDefault().isRegistered(this))
EventBus.getDefault().unregister(this);
}
public void onError(VolleyError volleyError)
{
UIHelper.stopProgressDialog(mProgressDialog);
Functions.Application.VolleyErrorCheck(this, volleyError);
}
just add this method to your viewPager adapter and your problem is solved.
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
this is override method of viewPager.
when you swipe one fragment to another it will automatically refresh page.
try this approach.. maybe its work for you..
put this code in your SubCategoryListAdepter
public void delete(int position) { //removes the row
superSubCategories.remove(position);
notifyItemRemoved(position);
}
make onClickListener to your ViewHolder:
suppose you click on your text and this row will be deleted.
#Override
public void onClick(View v) {
if(v.getId() == R.id.name){
//calls the method above to delete
delete(getAdapterPosition());
}
now you can also add data like this way.. thats working fine at runtime.. no need to refresh your page.

Categories

Resources