I implemented the recyclerview with layoutmanager in horizontal format in android studio. Everything was going well until android studio crashed. I managed to recover all my code but this time whenever I scroll, my textview items disappear. I have tried rebuilding using different API versions but the problem still persists. this is my code below:
MainActivity
public class MainActivity extends AppCompatActivity {
public static final String LOGTAG="kwik";
SalesDataSource salesDS;
SalesAdapter adapter;
Sales sales;
List<Sales> transaction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get the ViewPager and set it's PagerAdapter so that it can display items
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
// Give the PagerSlidingTabStrip the ViewPager
PagerSlidingTabStrip tabsStrip = (PagerSlidingTabStrip) findViewById(R.id.tabs);
// Attach the view pager to the tab strip
tabsStrip.setViewPager(viewPager);
}
}
MovieAdapter
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MyViewHolder>{
private List<MenuItem> menuItemList;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView menuItem;
public MyViewHolder(View view) {
super(view);
menuItem = (TextView) view.findViewById(R.id.tvMenuItem);
}
}
public MovieAdapter(List<MenuItem> menuItemList) {
this.menuItemList = menuItemList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.menu_item_row, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MenuItem menu = menuItemList.get(position);
holder.menuItem.setText(menu.getMenuItem());
}
#Override
public int getItemCount() {
return menuItemList.size();
}
}
try with
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
MenuItem menu = menuItemList.get(position);
holder.menuItem.setText(menu.getMenuItem());
}
final int position will give informations that textView inside cannot be changed
Related
I want to add ViewPager with tablayout in my RecyclerView row. But fragment I add in ViewPager just show in firts row, from second row, just TabLayout show, fragment in ViewPager not show. I read and found that I need set ID for each ViewPager. ViewPager does not allow sharing of the id in the same fragment, even if it is part of a recyclerview context. But I don'nt know how to do that. Anyone can show me what exactly step I need to do or another method ? Thanks you very much.
Code my RecyclerView Adapter
public class ListArtifactsAdapter extends
RecyclerView.Adapter<ListArtifactsAdapter.ListArtifactsViewHolder>
{
private List<Artifact> artifacts;
private Context context;
public static class ListArtifactsViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public ImageView mImageView;
public ViewPager mViewPager;
public TabLayout mTabLayout;
public ListArtifactsViewHolder(View itemView) {
super(itemView);
mTextView = (TextView)itemView.findViewById(R.id.titleTextView);
mImageView = (ImageView)itemView.findViewById(R.id.imageView);
View v = itemView.findViewById(R.id.function_tab);
mViewPager = (ViewPager)v.findViewById(R.id.pager);
mTabLayout = (TabLayout)v.findViewById(R.id.tab_layout);
}
}
public ListArtifactsAdapter(List<Artifact> artifacts, Context context){
this.artifacts = artifacts;
this.context = context;
}
#Override
public ListArtifactsAdapter.ListArtifactsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ListArtifactsViewHolder vh = new ListArtifactsViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_demo, parent, false));
return vh;
}
#Override
public void onBindViewHolder(ListArtifactsAdapter.ListArtifactsViewHolder holder, int position) {
Artifact artifact = artifacts.get(position);
holder.mTextView.setText(artifact.getName());
holder.mImageView.setImageResource(R.drawable.add);
holder.mViewPager.setAdapter(new ArtifactInformationAdapter(((AppCompatActivity)context).getSupportFragmentManager(), artifact.getAudio(), artifact.getTranscript()));
holder.mTabLayout.setupWithViewPager(holder.mViewPager);
}
#Override
public int getItemCount() {
return artifacts.size();
}
}
My ViewPager Adapter
public class ArtifactInformationAdapter extends FragmentStatePagerAdapter {
private List<Fragment> mFragmentList = new ArrayList<>();
private List<String> mFragmentTitleList = new ArrayList<>();
public ArtifactInformationAdapter(FragmentManager fragmentManager,String audio, String transcript) {
super(fragmentManager);
mFragmentList.add(AudioFragment.newInstance(audio));
mFragmentList.add(TranscriptFragment.newInstance(transcript));
mFragmentTitleList.add("Audio");
mFragmentTitleList.add("Transcript");
}
#Override
public int getCount() {
return mFragmentList.size();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
I have a setup a viewpager with 3 fragments. The first page of my viewpager contains data from a database. How can i implement a progress bar for only the first page just before the data gets loaded.
Custom fragment =>
public class HomeContentFragment extends Fragment {
public static ArrayList<ShishaBar> arrayList;
public static ContentAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
RecyclerView recyclerView = (RecyclerView) inflater.inflate(
R.layout.recycler_view, container, false);
adapter = new ContentAdapter();
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
new BackgroundWorker().execute();
return recyclerView;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ImageView picture;
public TextView name;
public TextView description;
public ViewHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater.inflate(R.layout.item_card, parent, false));
picture = (ImageView) itemView.findViewById(R.id.card_image);
name = (TextView) itemView.findViewById(R.id.card_title);
description = (TextView) itemView.findViewById(R.id.card_text);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context ctx = v.getContext();
Intent intent = new Intent(ctx, DetailActivity.class);
intent.putExtra(DetailActivity.EXTRA_POSITION, getAdapterPosition());
ctx.startActivity(intent);
}
});
}
}
public static class ContentAdapter extends RecyclerView.Adapter<ViewHolder> {
public ContentAdapter() {
arrayList = new ArrayList<>();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()), parent);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.picture.setImageBitmap(arrayList.get(position).getImage());
holder.name.setText(arrayList.get(position).getName());
holder.description.setText(arrayList.get(position).getStraat()+ " " + arrayList.get(position).getHuisnr()+ ", "+arrayList.get(position).getStad());
}
#Override
public int getItemCount() {
return arrayList.size();
}
}
}
If i put a progressbar on the viewpager, all the pages get the progress bar, I only want it on the first page. And if I put the progressbar in the xml of my card_view you can't see the progress bar until data is loaded.
in the adapter of the ViewPager, check the index of the page like:
public void instantiateItem(...,int position){
if(position == 0){
/* inflate a view that contains the ProgressBar and process it */
...
}
}
I have used ViewPager inside fragment with 4 tabs. Each tab has a RecyclerView which shows an image and the title for the movie. When I switch back and forth to this fragment from another fragment, there is memory leaks at every switch. I could not figure out at which place exactly does this happen.
Fragment class which has the ViewPager:
public class FragmentMoviesTab extends Fragment {
String[] tabTitles = {"Tab 1", "Tab 2", "Tab 3", "Tab 4"};
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
View view;
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_tab, container, false);
viewPager = (ViewPager) view.findViewById(R.id.viewPager);
viewPager.setPageTransformer(true, new AnimatePageTransformer());
FragmentStatePagerAdapter adapter = new FragmentStatePagerAdapter(getActivity().getSupportFragmentManager());
viewPager.setAdapter(adapter);
tabLayout = (TabLayout) view.findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(viewPager);
return view;
}
class FragmentStatePagerAdapter extends android.support.v4.app.FragmentStatePagerAdapter {
public FragmentStatePagerAdapter(FragmentManager manager) { super(manager); }
#Override
public Fragment getItem(int position) { return new RecyclerMovies(); }
#Override
public int getCount() { return tabTitles.length; }
#Override
public CharSequence getPageTitle(int position) { return tabTitles[position]; }
#Override
public Parcelable saveState() { return null; }
}
}
RecyclerFragment for each tab:
public class RecyclerMovies extends android.support.v4.app.Fragment {
View view;
RecyclerView recyclerView;
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.recycler, container, false);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setNestedScrollingEnabled(true);
RecyclerMoviesAdapter adapter = new RecyclerMoviesAdapter();
recyclerView.setAdapter(adapter);
return view;
}
public class RecyclerMoviesAdapter extends RecyclerView.Adapter<RecyclerMoviesAdapter.MyViewHolder> {
int[] movieTrailers = {R.drawable.movie_1, R.drawable.movie_2, R.drawable.movie_3, R.drawable.movie_4};
String[] movieNames = {"Movie A", "Movie B", "Movie C", "Movie D"};
#Override
public MyViewHolder onCreateViewHolder(ViewGroup viewGroup, final int i) {
View itemLayoutView = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.card_movie, viewGroup, false);
return new MyViewHolder(itemLayoutView);
}
#Override
public void onBindViewHolder(MyViewHolder viewHolder, int pos) {
final int position = viewHolder.getAdapterPosition();
viewHolder.movieName.setText(movieNames[position % 4]);
viewHolder.movieTrailer.setImageResource(movieTrailers[position % 4]);
}
#Override
public int getItemCount() {
return 10;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView movieName;
ImageView movieTrailer;
public MyViewHolder(View itemView) {
super(itemView);
movieName = (TextView) itemView.findViewById(R.id.movie_name);
movieTrailer = (ImageView) itemView.findViewById(R.id.movie_trailer);
}
}
}
}
Can someone point me to the correct direction where the memory leaks would be happening?
Memory leaks can be a pain to find, however there are tools out available that help you find and fix these leaks.
Take a look at LeakCanary, add this to your app and you'll get a notification whenever there is a memory leak. It also gives hints on what might be causing it.
Also, here's a link to a blog that shows some ways to avoid memory leaks in Android.
I've tried to post a similar questions without any answer, though of posting again.
The issue I am having is with viewing Fragment through Tabs, I have 3 Tabs in an AppBar displayed with ViewPager & FragmentPagerAdapter.
The problem is when the activity start, one of the tabs does not behave in a consistent way, upon logging in to the app & activity for the first time it would display the content of the Fragment ( Video clips ) but during switching between activities in the app, and going back to the Activity containing the 3 Tabs, choosing that specific Tab does not display anything, althou in the Logcat, i could tell it is retrieving Data related to the Vid Clip that should be displayed, also going back that Activity i see in the Logcat that even when i choose a different Tab, ( pictures ) Data from the 2 others Tab is being retrieved !?
The setup is as follows;
Main activity;
public class Member extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.member);
Firebase.setAndroidContext(this);
ButterKnife.bind(this);
// Adding Toolbar to Main screen
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Setting ViewPager for each Tabs
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
// Set Tabs inside Toolbar
TabLayout tabs = (TabLayout) findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
Adapter adapter = new Adapter(getSupportFragmentManager());
adapter.addFragment(new PicContentMMFragment(), "Pictures");
adapter.addFragment(new VidContentFragment(), "Videos");
adapter.addFragment(new LocationsContentFragment(), "Locations");
viewPager.setAdapter(adapter);
}
static class Adapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public Adapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
Well, as one of the users commented on the post pointed out that the problem could be from the specific fragemnt itself and not the way Tabs and Viewpager following is the VidContentFragment;
public class VidContentFragment extends android.support.v4.app.Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final RecyclerView recyclerView = (RecyclerView) inflater.inflate(
R.layout.recycler_view, container, false);
Log.i("MyTag_onCreate","vidContentFragment_Loaded");
ContentAdapter adapter = new ContentAdapter(recyclerView.getContext());
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return recyclerView;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public VideoView video;
public TextView authorName;
public TextView ratingValue;
public TextView locationValue;
public RatingBar ratingB;
public Button submitRating;
public LinearLayout placeNameHolder;
public int newRating;
public ViewHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater.inflate(R.layout.item_card_vid, parent, false));
authorName = (TextView) itemView.findViewById(R.id.card_title);
ratingValue = (TextView) itemView.findViewById(R.id.ratingValue);
locationValue = (TextView) itemView.findViewById(R.id.locationValue);
video = (VideoView) itemView.findViewById(R.id.placeVid);
ratingB = (RatingBar)itemView.findViewById(R.id.ratingBarMM);
ratingB.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
#Override
public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
newRating = (int) ratingB.getRating();
}
});
submitRating = (Button) itemView.findViewById(R.id.submitRatingMM);
submitRating.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
public_id = publicID[getPosition()];
Log.i("MyTag_Rating",public_id);
public static class ContentAdapter extends RecyclerView.Adapter<ViewHolder> {
// Set numbers of List in RecyclerView.
private Context mContext;
public ContentAdapter(Context context) {
this.mContext = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()), parent);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.authorName.setText(author[position]);
holder.ratingValue.setText(ratingV[position]);
holder.locationValue.setText(locationV[position]);
Uri video = Uri.parse(mVideos[position]);
holder.video.setVideoURI(video);
holder.video.setMediaController(new MediaController(mContext));
holder.video.requestFocus();
holder.video.seekTo(1000);
holder.video.pause();
try{
String url1 = mVideos[position];
URL ulrn = new URL(url1);
HttpURLConnection con = (HttpURLConnection)ulrn.openConnection();
InputStream is = con.getInputStream();
Bitmap bmp = BitmapFactory.decodeStream(is);
if (null != bmp)
Palette.generateAsync(bmp, new Palette.PaletteAsyncListener() {
public void onGenerated(Palette palette) {
int bgColor = palette.getVibrantColor(mContext.getResources().getColor(android.R.color.black));
holder.placeNameHolder.setBackgroundColor(bgColor);
}
});
else
Log.e("MyTag_BMP","The Bitmap is NULL");
}catch (Exception e){
}
}
#Override
public int getItemCount() {
return LENGTH;
}
}
}
Some part of the code (related to retrieving data from firebase) is left out to shorten it.
Although the other 2 fragments are organized the same way, the behavior of this fragment is inconsistent ?
Here is the version of the adapter with viewholder that I have for a recyclerview you said would likely be helpful. You'll need to refactor to adjust for your situation. I have gutted it mostly to help show just the bare interactions.
public class AnimalAdapter extends RecyclerView.Adapter<AnimalAdapter.AnimalCardViewHolder>{
private List<Animals> animalList;
public AnimalAdapter adapter = this;
Context context;
public AnimalAdapter(List<Animals> animalList, Context context) {
this.animalList = animalList;
this.context = context;
this.setInterface((iAdapterInterface) context);
}
#Override
public int getItemCount() {
return animalList.size();
}
#Override
public void onBindViewHolder(AnimalCardViewHolder holder, int position) {
Animals animal = animalList.get(position);
holder.txtName.setText(animal.getName());
holder.txtType.setText(animal.getType());
}
#Override
public AnimalCardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.animal_card_view, parent, false);
return new AnimalCardViewHolder(itemView);
}
public class AnimalCardViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
protected TextView txtName;
protected TextView txtType;
public AnimalCardViewHolder(final View itemView) {
super(itemView);
txtName = (TextView) itemView.findViewById(R.id.txtName);
txtType = (TextView) itemView.findViewById(R.id.txtType);
imgClose = (ImageView) itemView.findViewById(R.id.txtRemove);
listItem = itemView.findViewById(R.id.list_item);
listItem.setOnClickListener(this);
imgClose.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.txtRemove:
break;
case R.id.list_item:
break;
}
}
}
}
I am using FragmentStatePagerAdapter to load fragment with viewpager with tab layout. I am passing different id's to load same fragment with different data in getItem() but it is always returning fragment with same data on first time and when I swipe through next screens and came back to first screen then it will showing correct data.
Any solution or info is very helpful.
I am calling adapter like this in my onCreate() and it always return same data for position 0 and 1.
MyPagerAdapter adapter = new MyPagerAdapter (getSupportFragmentManager(),bundle);
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
My Adapter
static class MyPagerAdapter extends FragmentStatePagerAdapter {
private Bundle b;
public MyPagerAdapter (FragmentManager fm,Bundle b) {
super(fm);
this.b=b;
}
#Override
public Fragment getItem(int position) {
ContentListFragment fragment = new ContentListFragment();
b.putString("id", tabList.get(position).get("id"));
fragment.setArguments(b);
return fragment;
}
#Override
public int getCount() {
return tabList.size();
}
#Override
public CharSequence getPageTitle(int position) {
return tabList.get(position).get("title");
}
}
Edit
ContentListFragment.java
public class ContentListFragment extends Fragment{
private static final String TAG="ContentListFragment";
private String id,type;
private TextView norecord;
private View rootView;
private List<AppReading> appReadingList;
private RecyclerView recyclerView;
private ContentRecyclerAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
Log.d(TAG, "onCreateView");
rootView = inflater.inflate(R.layout.content_list, container,false);
initView();
initData();
return rootView;
}
private void initView() {
// TODO Auto-generated method stub
norecord=(TextView)rootView.findViewById(R.id.norecord);
recyclerView=(RecyclerView) rootView.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
}
private void initData() {
id=getArguments().getString("id");
getContentList(category);
}
// Get records by category
private void getContentList(String id){
Log.d(TAG, "getContentList: "+id);
Dao dao=new Dao(getActivity());
dao.open();
appReadingList=dao.getContentList(id);
dao.close();
//Set adapter if data available
if(appReadingList.size()>0){
adapter=new ContentRecyclerAdapter();
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(),R.drawable.divider));
recyclerView.setItemAnimator(new FadeInLeftAnimator());
recyclerView.setAdapter(new SlideInLeftAnimationAdapter(adapter));
}else{
norecord.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
}
}
private class ContentRecyclerAdapter extends RecyclerView.Adapter<ContentRecyclerAdapter.ViewHolder>{
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.listitem, parent, false);
ViewHolder holder = new ViewHolder(v);
return holder;
}
#Override
public void onBindViewHolder(ViewHolder holder,final int position) {
holder.itemContent.setText(appReadingList.get(position).getTitle());
holder.itemDate.setText(appReadingList.get(position).getAddDate());
}
#Override
public int getItemCount() {
return appReadingList.size();
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
class ViewHolder extends RecyclerView.ViewHolder{
TextView itemContent, itemDate ;
RelativeLayout listItem;
ViewHolder(View itemView){
super(itemView);
itemContent = (TextView) itemView.findViewById(R.id.itemcontent);
itemDate = (TextView) itemView.findViewById(R.id.itemdate);
listItem=(RelativeLayout) itemView.findViewById(R.id.rlListItem);
}
}
}