I am making an app to upload photos and show them in a gallery.
When I run my app it doesn't load the photos from firebase database. It gives me the error:
No adapter attached; skipping layout
I tried many solutions but all failed.
This is the activity:
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;
public class ImagesActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private ImageAdapter mAdapter;
private DatabaseReference mDatabaseRef;
private List<Upload> mUploads;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_images);
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mUploads = new ArrayList<>();
mDatabaseRef = FirebaseDatabase.getInstance().getReference("uploads");
mDatabaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
Upload upload = postSnapshot.getValue(Upload.class);
mUploads.add(upload);
}
mAdapter = new ImageAdapter(ImagesActivity.this, mUploads);
mRecyclerView.setAdapter(mAdapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(ImagesActivity.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
and this is the adapter:
package com.example.android.shoftoh1;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.android.shoftoh1.R;
import com.example.android.shoftoh1.Upload;
import com.squareup.picasso.Picasso;
import java.util.List;
// Create the basic adapter extending from RecyclerView.Adapter
// Note that we specify the custom ViewHolder which gives us access to our views
public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ImageViewHolder> {
private Context mContext;
private List<Upload> mUploads;
public ImageAdapter(Context context, List<Upload> uploads) {
mContext = context;
mUploads = uploads;
}
#NonNull
#Override
public ImageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(mContext).inflate(R.layout.image_item, parent, false);
return new ImageViewHolder(v);
}
#Override
public void onBindViewHolder(ImageViewHolder holder, int position) {
Upload uploadCurrent = mUploads.get(position);
holder.textViewName.setText(uploadCurrent.getName());
Picasso.get()
.load(uploadCurrent.getImageUrl())
.fit()
.centerCrop()
.into(holder.imageView);
}
#Override
public int getItemCount() {
return mUploads.size();
}
// Provide a direct reference to each of the views within a data item
// Used to cache the views within the item layout for fast access
static class ImageViewHolder extends RecyclerView.ViewHolder {
// Your holder should contain a member variable
// for any view that will be set as you render a row
TextView textViewName;
ImageView imageView;
// We also create a constructor that accepts the entire item row
// and does the view lookups to find each subview
ImageViewHolder(View itemView) {
// Stores the itemView in a public final member variable that can be used
// to access the context from any ViewHolder instance.
super(itemView);
textViewName = itemView.findViewById(R.id.text_view_name);
imageView = itemView.findViewById(R.id.image_view_upload);
}
}
}
Appreciate your help.
Try making this ImageViewHolder public
// Provide a direct reference to each of the views within a data item
// Used to cache the views within the item layout for fast access
public class ImageViewHolder extends RecyclerView.ViewHolder {
// Your holder should contain a member variable
// for any view that will be set as you render a row
public TextView textViewName;
public ImageView imageView;
// We also create a constructor that accepts the entire item row
// and does the view lookups to find each subview
public ImageViewHolder(View itemView) {
// Stores the itemView in a public final member variable that can be used
// to access the context from any ViewHolder instance.
super(itemView);
textViewName = itemView.findViewById(R.id.text_view_name);
imageView = itemView.findViewById(R.id.image_view_upload);
}
}
}
First of all, try to attach the adapter with empty list then call notifyDataSetChanged() on updating the list as :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_images);
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mUploads = new ArrayList<>();
// attach the adapter with the empty list
mAdapter = new ImageAdapter(ImagesActivity.this, mUploads);
mRecyclerView.setAdapter(mAdapter);
mDatabaseRef = FirebaseDatabase.getInstance().getReference("uploads");
mDatabaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
Upload upload = postSnapshot.getValue(Upload.class);
mUploads.add(upload);
}
//now that mUploads has been updated call notifyDataSetChanged().
//Also, if you know the position that was inserted you can
//use other variant such as notifyItemInserted().
mAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(ImagesActivity.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
I suggest that you try to:
Move the adapter from the Firebase function to the rows that
define the Recycler View
Then update the list containing the data from Firebase (this can be the same list)
Finally, update the adapter that was made.
Good luck,
Well done!
Related
I am absolute beginner for this, I'm sorry if this such a dumb mistakes.
so, I created fragment in which i have got recyclerView, but my recycler view is empty, i saw that my context is empty, and i think, that it can be the reason of this, i try to use getActivity
here is code of my fragment
package com.example.pocketcinema;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;
import java.util.ArrayList;
import java.util.List;
public class SearchFragment extends Fragment implements RecyclerViewInterface {
private RecyclerView recyclerView;
RecyclerViewInterface rci;
MyAdapter myAdapter;
public List<String> nameOfFilm, youTubeUrl, photoUrl, descriptionToFilm, category;
FirebaseFirestore db = FirebaseFirestore.getInstance();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
recyclerView = inflater.inflate(R.layout.fragment_search, container,
false).findViewById(R.id.filmsList);
rci = this;
nameOfFilm = new ArrayList<>();
youTubeUrl = new ArrayList<>();
photoUrl = new ArrayList<>();
descriptionToFilm = new ArrayList<>();
category = new ArrayList<>();
loadFilmsFromDB();
return inflater.inflate(R.layout.fragment_search, container, false);
}
private void loadFilmsFromDB() {
Context context = requireContext();
db.collection("films").get().addOnCompleteListener(new
OnCompleteListener<QuerySnapshot>()
{
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
for (QueryDocumentSnapshot document : task.getResult()) {
nameOfFilm.add(document.get("nameOfFilm").toString());
descriptionToFilm.add(document.get("descriptionToFilm").toString());
photoUrl.add(document.get("imageUrl").toString());
youTubeUrl.add(document.get("videoURL").toString());
category.add(document.get("category").toString());
myAdapter = new MyAdapter(context, nameOfFilm, descriptionToFilm,
photoUrl, youTubeUrl,
rci, category);
recyclerView.setAdapter(myAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
}
}
});
}
here is screenshot with debuger, you can see that context = null
context = null
here you can see that i set layout for recyclerView
with logcat
here is Adapter
package com.example.pocketcinema;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import com.squareup.picasso.Picasso;
import java.util.List;
public class MyAdapter extends
RecyclerView.Adapter<MyAdapter.MyViewHolder> {
Context ct;
List<String> name, description, image, video, category;
private final RecyclerViewInterface recyclerViewInterface;
public MyAdapter(Context ct, List<String> nameOfFilm, List<String>
descriptionOfFilm, List<String> imageUrl, List<String> videoUrl,
RecyclerViewInterface rci,List<String> category) {
name = nameOfFilm;
description = descriptionOfFilm;
image = imageUrl;
video = videoUrl;
this.ct = ct;
recyclerViewInterface = rci;
this.category = category;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int
viewType) {
LayoutInflater inflater = LayoutInflater.from(ct);
View view = inflater.inflate(R.layout.my_row, parent, false);
return new MyViewHolder(view, recyclerViewInterface);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int
position) {
holder.nameFilm.setText(name.get(position));
holder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(ct, PlayerActivity.class);
}
});
Picasso.get().load(image.get(position)).into(holder.image2);
}
#Override
public int getItemCount() {
return image.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView nameFilm;
ImageView image2;
CardView cardView;
public MyViewHolder(#NonNull View itemView, RecyclerViewInterface
recyclerViewInterface) {
super(itemView);
nameFilm = itemView.findViewById(R.id.nameTV);
image2 = itemView.findViewById(R.id.imageView2);
cardView = itemView.findViewById(R.id.cardView);
itemView.findViewById(R.id.sectionOFRecyclerView).setOnClickListener
(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (recyclerViewInterface != null) {
int pos = getAdapterPosition();
if (pos != RecyclerView.NO_POSITION) {
recyclerViewInterface.onItemClick(pos);
}
}
}
});
}
}
}
myAdapter isn't null
You are trying to create an instance of activity as global variable. That means the context has not been generated yet.
Basically you can just use requireContext() method of Fragment class. This will provide you the context.
As I have mentioned in comment, you need to update your onCreateView method as below:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_search, container, false);
}
Then, you need to initialize your view and other stuff on onViewCreated method. You can update that method like this:
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.filmsList);
textView = view.findViewById(R.id.test);
rci = this;
nameOfFilm = new ArrayList<>();
youTubeUrl = new ArrayList<>();
photoUrl = new ArrayList<>();
descriptionToFilm = new ArrayList<>();
category = new ArrayList<>();
loadFilmsFromDB();
}
Notes
You don't have to send many string parameters to your adapter. It is better to create a Model class for that item, and send the list of that item. So, model classes will have all the data you need, and you can use them from that model. This will give you better coding style and will let you manage your data easier.
To communicate with your XML layout, you can use ViewBinding or DataBinding for that. This will also help you to use your view elements without creating variables for each of them.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 1 year ago.
I have utilized mContext through "recyclerAdapter = new RecyclerAdapter(mContext, placeList);" but at the variable declaration, android studio mentioned that it was never assigned. What is the error here?
The main purpose of this is so that I can retrieve both text and images from firebase to android studio.
package com.example.myapplication;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
//firebase
//FirebaseDatabase firebaseDatabase;
private DatabaseReference myRef;
//Widgets
RecyclerView recyclerView;
//variables
private ArrayList<Place> placeList;
private RecyclerAdapter recyclerAdapter;
private Context mContext;//Private field 'mContext' is never assigned
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//set recyclerView
recyclerView = findViewById(R.id.recyclerView);
LinearLayoutManager LayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(LayoutManager);
recyclerView.setHasFixedSize(true);
//set Firebase
myRef = FirebaseDatabase.getInstance().getReference();
//set arraylist
placeList = new ArrayList<>();
//get a data method
GetDataFromFirebase();
//Clear Arraylist
ClearAll();
}
//this is data method
private void GetDataFromFirebase() {
Query query = myRef.child("places1");
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
ClearAll();
for (DataSnapshot ds: snapshot.getChildren()){
Place place = new Place();
place.setImage(ds.child("image").getValue().toString()); //place image to "image:"
place.setName(ds.child("name").getValue().toString());
place.setLocation(ds.child("location").getValue().toString());
placeList.add(place);
}
recyclerAdapter = new RecyclerAdapter(mContext, placeList);//mContext is being used here
recyclerView.setAdapter(recyclerAdapter);
recyclerAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
private void ClearAll(){
if (placeList != null){
placeList.clear();
if(recyclerAdapter!=null){
recyclerAdapter.notifyDataSetChanged();
}
}
placeList = new ArrayList<>();
}
}
mContext was also used in my another class file called RecyclerAdapter.java
package com.example.myapplication;
import android.content.Context;
import android.icu.text.Transliterator;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private static final String Tag = "RecyclerView";
private Context mContext;
private ArrayList<Place> placeList;
public RecyclerAdapter(Context mContext, ArrayList<Place> placeList) {
this.mContext = mContext;
this.placeList = placeList;
}
#NonNull
#Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//call viewholder to place the data in this template
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.place_info, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
//get textview
holder.textView1.setText(placeList.get(position).getName());
holder.textView2.setText(placeList.get(position).getName());
//image view using glide lib
Glide.with(mContext)
.load(placeList.get(position).getImage())
.into(holder.imageView); //diaply into image view
}
#Override
public int getItemCount() {
return placeList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
//widgets
ImageView imageView;
TextView textView1;
TextView textView2;
public ViewHolder(#NonNull View itemView) {
super(itemView);
imageView =itemView.findViewById(R.id.imageView);
textView1=itemView.findViewById(R.id.textViewName);
textView2=itemView.findViewById(R.id.textViewLocation);
}
}
}
Replace this:
Glide.with(mContext)
.load(placeList.get(position).getImage())
.into(holder.imageView);
with this:
Glide.with(holder.itemView.getContext())
.load(placeList.get(position).getImage())
.into(holder.imageView);
After doing this, you no longer need the "mContext" :)
(Neither in the constructor nor in the class)
Please let me know if this works.
I have an app trying to show its items from the latest item added to earlier ones in a grid view with GridLayoutManager, getting the items from firebase database, setReverseLayout works but when the items are not uniform or items total is an odd number, it leaves a vacant space for on item at the top like it omitted an item but it didnt, i tried using collections.reverse but it didnt really arrange the items from latest items, more like shuffled it and i still have that gap problem at the top. There is no error message, the app runs fine but its not displaying items the desired way.
Here is a screenshot of the problem with both methods I tried
Here is my recycler adapter code
package com.example.twelve.Adapters;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.twelve.HomeActivity;
import com.example.twelve.Model.HomeProducts;
import com.example.twelve.Products_Page_Activity;
import com.example.twelve.R;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.List;
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
List<HomeProducts> lstproducts = new ArrayList<>();
Context ncontext;
public RecyclerAdapter(List<HomeProducts> lstproducts, Context ncontext) {
this.lstproducts = lstproducts;
this.ncontext = ncontext;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(ncontext).inflate(R.layout.home_product_items, parent, false));
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, final int position) {
holder.cardview_pname.setText(lstproducts.get(position).getPname());
holder.cardview_category.setText(lstproducts.get(position).getCategory());
holder.cardview_price.setText(lstproducts.get(position).getPrice());
Picasso.get().load(lstproducts.get(position).getImageurllist().get(0)).into(holder.cardview_image);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), Products_Page_Activity.class);
intent.putExtra("pid", lstproducts.get(position).getPid());
intent.putExtra("prev_activity", "Home");
view.getContext().startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return lstproducts.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ImageView cardview_image;
public TextView cardview_pname, cardview_category, cardview_price;
public ViewHolder(#NonNull View itemView) {
super(itemView);
cardview_image = itemView.findViewById(R.id.rec_imgview);
cardview_pname = itemView.findViewById(R.id.rec_textviewname);
cardview_category = itemView.findViewById(R.id.rec_textviewcategory);
cardview_price = itemView.findViewById(R.id.rec_textprice);
}
}
}
Code to add products to the adapter
//Products are added in a list and passed to the adapter
DatabaseReference pref = FirebaseDatabase.getInstance().getReference("HomeProducts");
pref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for(DataSnapshot dataSnapshot : snapshot.getChildren()){
HomeProducts Hproducts = dataSnapshot.getValue(HomeProducts.class);
listtems.add(Hproducts);
Collections.reverse(listtems);
}
rcyAdapter = new RecyclerAdapter(listtems, HomeActivity.this);
rcyAdapter.notifyDataSetChanged();
recyclerView.setAdapter(rcyAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
try to get Collections.reverse(listtems); out of the for loop .. just after its end brace to complete getting all the items of the collection first and then reverse it
you should use setStackFromEnd :
GridLayoutManager manager = new GridLayoutManager(this, 2);
manager.setStackFromEnd(true);
This is the first time I'm going for a recycled view, I added the adaptor class and all, no errors in the code but nothing shows up. I did everything according to the first answer in this post Simple Android RecyclerView example but still there is something that I'm doing wrong and I don't know where to look for it. In the Run log I found this error
Caused by: java.lang.ClassNotFoundException: Didn't find class "android.view.View$OnUnhandledKeyEventListener" on path: DexPathList
but I tried fixing it with what I found online but still it didn't work
package com.mircea.bookapp;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class BookActivity extends AppCompatActivity implements BookListViewAdapter.ItemClickListener {
BookListViewAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_book);
//Hardcoded books
List<Book> books = new ArrayList<>();
books.add(new Book(" In Search of Lost Time", "Marcel Proust", 1913, "modernist"));
books.add(new Book(" In Search of Lost Time", "Marcel Proust", 1913, "modernist"));
books.add(new Book(" In Search of Lost Time", "Marcel Proust", 1913, "modernist"));
books.add(new Book(" In Search of Lost Time", "Marcel Proust", 1913, "modernist"));
books.add(new Book(" In Search of Lost Time", "Marcel Proust", 1913, "modernist"));
// set up the RecyclerView
RecyclerView recyclerView = findViewById(R.id.booklist);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new BookListViewAdapter(this, books);
adapter.setClickListener(this);
recyclerView.setAdapter(adapter);
}
#Override
public void onItemClick(View view, int position) {
Toast.makeText(this, "You clicked " + adapter.getItem(position) + " on row number " + position, Toast.LENGTH_SHORT).show();
}
}
What am I doing wrong? Also here is the code for the BookListViewAdapter class
package com.mircea.bookapp;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class BookListViewAdapter extends RecyclerView.Adapter<BookListViewAdapter.ViewHolder> {
private List<Book> mData;
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
// data is passed into the constructor
BookListViewAdapter(Context context, List<Book> data) {
this.mInflater = LayoutInflater.from(context);
this.mData = data;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
// inflates the row layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.recyclerview_row, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull BookListViewAdapter.ViewHolder holder, int position) {
}
#Override
public int getItemCount() {
return mData.size();
}
// convenience method for getting data at click position
Book getItem(int id) {
return mData.get(id);
}
// allows clicks events to be caught
void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView myTextView;
ViewHolder(View itemView) {
super(itemView);
myTextView = itemView.findViewById(R.id.bookTitle);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
}
}
}
You need to setText in onBindViewHolder
#Override
public void onBindViewHolder(#NonNull BookListViewAdapter.ViewHolder holder, int position) {
holder. myTextView.setText()//the text you want
}
I think the problem is that you forgot to add your ArrayList. Try adding it with your RecyclerView setup code.
RecyclerView recyclerView = findViewById(R.id.booklist);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// Add ArrayList here
adapter = new BookListViewAdapter(this, books);
adapter.setClickListener(this);
recyclerView.setAdapter(adapter);
I want to build an app by which I can generate bussiness card. So I use navigaion drawer. For navigating menus I use fragment class for each of the menus and corresponding XML layout. In one of the layout I want to show my card view inside recyclerview.
MycardFragment.java
(This is the fragment class where I want show recyclerview)
package com.example.look.np.fragments;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.TextView;
import com.example.look.np.R;
import com.example.look.np.models.Template;
import com.example.look.np.utils.FirebaseMethod;
import com.example.look.np.utils.RecyclerviewAdapter;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;
public class MyCardFragment extends Fragment {
private static final String TAG = "MyCardFragment";
private Context mContext;
private RecyclerView recyclerView;
FirebaseDatabase database;
DatabaseReference myRef ;
List<Template> listdata;
public MyCardFragment() {
// Required empty public constructor
}
//i tried this section but it gimes me error
#Override
public void onAttach(Context context) {
super.onAttach(context);
mContext=context;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_mycards,container,false);
database = FirebaseDatabase.getInstance();
myRef = database.getReference("template");
// Initialize Template Model Class
Template template = new Template();
// ...
// Lookup the Recycler view in fragment layout
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
// Attach the adapter to the recyclerview to populate items
RecyclerviewAdapter adapter = new RecyclerviewAdapter(template,inflater.getContext());//>>>This is the error i'm facig
// Set layout manager to position the items
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
listdata = new ArrayList<Template>();
for(DataSnapshot dataSnapshot1 :dataSnapshot.child("template").getChildren()){
Template value = dataSnapshot1.getValue(Template.class);
Template fire = new Template();
String name = value.getP_name();
String desig = value.getP_designation();
String email = value.getP_email();
String phone = value.getP_phone();
String address = value.getC_address();
String c_name = value.getC_name();
fire.setP_name(name);
fire.setP_designation(desig);
fire.setP_email(email);
fire.setP_phone(phone);
fire.setC_name(c_name);
fire.setC_address(address);
listdata.add(fire);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
// Failed to read value
Log.w("Hello", "Failed to read value.", databaseError.toException());
}
});
return view;
}
#Override
public void onStart() {
super.onStart();
}
}
I aslo created an adapter for recycler view, when I want to set the adapter to the fragment class it shows error. It takes context and List. For context I add getActivity() bMycardFragment.java
(This is the fragment class where I want show recyclerview)
package com.example.look.np.fragments;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.TextView;
import com.example.look.np.R;
import com.example.look.np.models.Template;
import com.example.look.np.utils.FirebaseMethod;
import com.example.look.np.utils.RecyclerviewAdapter;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;
public class MyCardFragment extends Fragment {
private static final String TAG = "MyCardFragment";
private Context mContext;
private RecyclerView recyclerView;
FirebaseDatabase database;
DatabaseReference myRef ;
List<Template> listdata;
public MyCardFragment() {
// Required empty public constructor
}
//i tried this section but it gimes me error
#Override
public void onAttach(Context context) {
super.onAttach(context);
mContext=context;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_mycards,container,false);
database = FirebaseDatabase.getInstance();
myRef = database.getReference("template");
// Initialize Template Model Class
Template template = new Template();
// ...
// Lookup the Recycler view in fragment layout
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
// Attach the adapter to the recyclerview to populate items
RecyclerviewAdapter adapter = new RecyclerviewAdapter(template,inflater.getContext());//>>>This is the error i'm facig
// Set layout manager to position the items
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
listdata = new ArrayList<Template>();
for(DataSnapshot dataSnapshot1 :dataSnapshot.child("template").getChildren()){
Template value = dataSnapshot1.getValue(Template.class);
Template fire = new Template();
String name = value.getP_name();
String desig = value.getP_designation();
String email = value.getP_email();
String phone = value.getP_phone();
String address = value.getC_address();
String c_name = value.getC_name();
fire.setP_name(name);
fire.setP_designation(desig);
fire.setP_email(email);
fire.setP_phone(phone);
fire.setC_name(c_name);
fire.setC_address(address);
listdata.add(fire);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
// Failed to read value
Log.w("Hello", "Failed to read value.", databaseError.toException());
}
});
return view;
}
#Override
public void onStart() {
super.onStart();
}
}
MycardFragment.java
(This is the fragment class where I want show recyclerview)
package com.example.look.np.fragments;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.TextView;
import com.example.look.np.R;
import com.example.look.np.models.Template;
import com.example.look.np.utils.FirebaseMethod;
import com.example.look.np.utils.RecyclerviewAdapter;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;
public class MyCardFragment extends Fragment {
private static final String TAG = "MyCardFragment";
private Context mContext;
private RecyclerView recyclerView;
FirebaseDatabase database;
DatabaseReference myRef ;
List<Template> listdata;
public MyCardFragment() {
// Required empty public constructor
}
//i tried this section but it gimes me error
#Override
public void onAttach(Context context) {
super.onAttach(context);
mContext=context;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_mycards,container,false);
database = FirebaseDatabase.getInstance();
myRef = database.getReference("template");
// Initialize Template Model Class
Template template = new Template();
// ...
// Lookup the Recycler view in fragment layout
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
// Attach the adapter to the recyclerview to populate items
RecyclerviewAdapter adapter = new RecyclerviewAdapter(template,inflater.getContext());//>>>This is the error i'm facig
// Set layout manager to position the items
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
listdata = new ArrayList<Template>();
for(DataSnapshot dataSnapshot1 :dataSnapshot.child("template").getChildren()){
Template value = dataSnapshot1.getValue(Template.class);
Template fire = new Template();
String name = value.getP_name();
String desig = value.getP_designation();
String email = value.getP_email();
String phone = value.getP_phone();
String address = value.getC_address();
String c_name = value.getC_name();
fire.setP_name(name);
fire.setP_designation(desig);
fire.setP_email(email);
fire.setP_phone(phone);
fire.setC_name(c_name);
fire.setC_address(address);
listdata.add(fire);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
// Failed to read value
Log.w("Hello", "Failed to read value.", databaseError.toException());
}
});
return view;
}
#Override
public void onStart() {
super.onStart();
}
}
I have an adapter class which takes context and List of items. Now I want to set my adapter in a fragment by passing context (getActivity() and List but it shows me error
I tried getActivity() but it show me error
i also tried this
#Override
public void onAttach(Context context) {
super.onAttach(context);
mContext=context;
}
//This is adapter class for my Recyclerview
RecyclerAdater.java
package com.example.look.np.utils;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.example.look.np.R;
import com.example.look.np.models.Template;
import java.util.List;
public class RecyclerviewAdapter extends RecyclerView.Adapter<RecyclerviewAdapter.MyHolder>{
// ... constructor and member variables
// Usually involves inflating a layout from XML and returning the holder
List<Template> listdata;
Context context;
public RecyclerviewAdapter(List<Template> listdata, Context context) {
this.listdata = listdata;
this.context = context;
}
#Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Inflate the custom layout
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview,parent,false);
// Return a new holder instance
MyHolder myHolder = new MyHolder(view);
return myHolder;
}
public void onBindViewHolder(MyHolder holder, int position) {
Template data = listdata.get(position);
holder.pname.setText(data.getP_name());
holder.pdesignation.setText(data.getP_designation());
holder.pemail.setText(data.getP_email());
holder.pphone.setText(data.getP_phone());
holder.cname.setText(data.getC_name());
holder.caddress.setText(data.getC_address());
}
#Override
public int getItemCount() {
//return listdata.size();
int arr = 0;
try{
if(listdata.size()==0){
arr = 0;
}
else{
arr=listdata.size();
}
}catch (Exception e){
e.printStackTrace();
}
return arr;
}
class MyHolder extends RecyclerView.ViewHolder{
// Your holder should contain a member variable
// for any view that will be set as you render a row
TextView pname,caddress,pemail,pdesignation,pphone,cname;
// We also create a constructor that accepts the entire item row
// and does the view lookups to find each subview
public MyHolder(View itemView) {
// Stores the itemView in a public final member variable that can be used
// to access the context from any ViewHolder instance.
super(itemView);
pname = (TextView) itemView.findViewById(R.id.txt_personName);
caddress = (TextView) itemView.findViewById(R.id.txt_address);
pemail = (TextView) itemView.findViewById(R.id.txt_email);
pdesignation = (TextView) itemView.findViewById(R.id.txt_designation);
pphone = (TextView) itemView.findViewById(R.id.txt_phone);
cname = (TextView) itemView.findViewById(R.id.txt_companyName);
}
}
}
Point to be noted, don't forget to set layoutManager to recyclerview and to set adapter.
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL
recyclerview.setLayoutManager(layoutManager);
recyclerview.setHasFixedSize(true);
recyclerviewAdapter adapter = new recyclerviewAdapterAdapter(listdata,getActivity());
recyclerview.setAdapter(adapter);
Another thing to notice in your code is:
There is network call (Which run in background) in oncreateView(). Before it gives result, the return view; is getting called.
This means the view is not updated while on background job is going.
This can be resolved by calling separate method like setRecyclerView() from onCreateView() method. After getting result from background operation you can set your recyclerview as mentioned above.
Don't forget to call the adapter.notifydatasetchanged() method.