I am working on printing all users based on the UID, but I only get one user printed.
This is the result I am getting now.
Here is what the printingUserList(), this is a small function to retrieve all user information based on UID.
RecyclerView rv;
UserAdapter usrAdapter;
ArrayList<User> mUsrsList;
private void readUsrs(){
LinearLayoutManager LayoutManager = new LinearLayoutManager(this);
rv.setLayoutManager(LayoutManager);
mUsrsList = new ArrayList<>();
final FirebaseUser me = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("users");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mUsrsList.clear();
for (DataSnapshot ds: dataSnapshot.getChildren()) {
Log.d("TAG_", "A++" + dataSnapshot.getChildrenCount()); //prints 5, which exactly has five users in the database.
User all_usr = ds.getValue(User.class);
if (!all_usr.getUid().equals(me.getUid())) { //won't print itself
mUsrsList.add(all_usr);
}
}
System.out.println(mUsrsList.toString());
usrAdapter = new UserAdapter(RoomUser_Activity.this, mUsrsList);
rv.setAdapter(usrAdapter);
usrAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) { }
});
}
and this is the recyclerview, should be correct otherwise it prints nothing
public class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserViewHolder> {
private Context m_context;
private ArrayList<User> all_users;
public static final String EXTRA_HISUID = "NoHisUID";
public UserAdapter(Context context, ArrayList<User> all_users) {
this.m_context = context;
this.all_users = all_users;
}
#NonNull
#Override
public UserAdapter.UserViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(m_context);
View itemv = inflater.inflate(R.layout.layout_item_user, parent, false); //xml provide below
return new UserViewHolder(itemv);
}
public class UserViewHolder extends RecyclerView.ViewHolder{
public ImageView UserIcon; //default icon provided in xml
public TextView Username;
public UserViewHolder (View itemView){
super(itemView);
UserIcon = (ImageView)itemView.findViewById(R.id.usr_icon);
Username = (TextView)itemView.findViewById(R.id.tv_username);
}
}
public void onBindViewHolder(#NonNull UserAdapter.UserViewHolder holder, int position) {
User usr = all_users.get(position);
final String hisUID = usr.getUid();
holder.Username.setText(usr.getUsername());
if(usr.getIcon().equals("default_icon")){
holder.UserIcon.setImageResource(R.drawable.default_icon);
}
else{
Glide.with(m_context).load(usr.getIcon()).into(holder.UserIcon);
}
}
public int getItemCount() {
return all_users.size();
}
layout_item_user.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:padding="10dp"
android:layout_height="match_parent">
<ImageView
android:id="#+id/usr_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#mipmap/ic_launcher" />
<TextView
android:id="#+id/tv_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="13dp"
android:layout_toEndOf="#+id/usr_icon"
android:layout_toRightOf="#+id/usr_icon"
android:text="username"
android:textSize="18sp" />
<TextView
android:id="#+id/lastMessageTv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="The last message"
android:layout_marginStart="4dp"
android:maxLines="2"
android:layout_marginTop="3dp"
android:layout_toRightOf="#id/usr_icon"
android:layout_below="#id/tv_username"
android:layout_marginLeft="13dp" />
</RelativeLayout>
database:
users:
|-2NUPkQuHFRS49ZHDZzEtWiErIiv1
|-address: "920 West 4th Ave apt231"
|-city: "blank"
|-donut: 0
|-email: "not_busy#gmail.com"
|-full_name: "blank"
|-icon: "default_icon"
|-phone: "253353309"
|-state: "blank"
|-uid: "2NUPkQuHFRS49ZHDZzEtWiErIiv1"
|-username: "not_busy"
|-F0NRthr8uJPYMz2o129w2PAf30i1
|-GRJPA5hKA6aRgNl68sSxv3xruww1
|-W0PIUjUwRHXTkooztYFuhKuLItE3
|-cBzUNHceM2T47cr0zWX1tqgB2wA3
It must be a small bug, but I still cannot figure what problem is.. thank you in advance.
Related
I took this adapter from the internet and I got a problem:
Fatal Exception: java.lang.NullPointerException
Attempt to invoke virtual method 'void android.widget.ImageView.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
.Consts.CustomFriendsRequets.getView
Here CustomFriendRequest is my adapter, and its copy works fine, but this one doesn't want. The error refers to line 104, namely viewHolder.add.setOnClickListener (v ->. I spent several days going through the code, trying to figure out what was wrong.
Here is the complete adapter code. CustomFriendsRequets:
class CustomFriendsRequets extends ArrayAdapter<addFriends> implements View.OnClickListener{
private ArrayList<addFriends> dataSet;
private String uid, uid2;
private DatabaseReference isRef;
Context mContext;
// View lookup cache
private static class ViewHolder {
TextView txtName;
TextView txtType;
ImageView info;
ImageView add;
ImageView del;
}
public CustomFriendsRequets(ArrayList<addFriends> data, Context context) {
super(context, R.layout.friends_requests_item, data);
this.dataSet = data;
this.mContext=context;
}
#Override
public void onClick(View v) {
int position=(Integer) v.getTag();
Object object= getItem(position);
addFriends dataModel=(addFriends) object;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
addFriends dataModel = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.friends_item, parent, false);
viewHolder.txtName = convertView.findViewById(R.id.tvDescr);
viewHolder.txtType = convertView.findViewById(R.id.tvPrice);
viewHolder.info = convertView.findViewById(R.id.uImgreqs);
viewHolder.add = convertView.findViewById(R.id.ibAdd);
viewHolder.del = convertView.findViewById(R.id.ibDel);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();if(user!=null){uid=user.getUid();}
uid2 = dataModel.uid2;
viewHolder.txtName.setText(dataModel.username1);
viewHolder.txtType.setText("хочет добавить вас в друзья");
viewHolder.info.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getContext(), EnemyProfile.class);
intent.putExtra(Constant.UID, dataModel.uid2);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
v.getContext().startActivity(intent);
}
});
isRef = FirebaseDatabase.getInstance().getReference();
viewHolder.add.setOnClickListener(v -> //error here
isRef.child("Users").child("info").child(uid2).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
Users info = snapshot.getValue(Users.class);
if (info!=null){
String name = info.username;
String id = info.uid;
addFriends adf = new addFriends(id, name);
isRef.child("Users").child(uid).child("Friends").setValue(adf).
addOnSuccessListener(aVoid ->
isRef.child("Users").child("info").child(uid).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot1) {
Users minfo = snapshot1.getValue(Users.class);
if (minfo!=null){
String mname = minfo.username;
String mid = minfo.uid;
addFriends madf = new addFriends(mid, mname);
isRef.child("Users").child(uid2).child("Friends").setValue(madf)
.addOnSuccessListener(aVoid1 -> {
isRef.child("Users").child(uid).child("Friends-request").child(uid2).removeValue();
isRef.child("Users").child(uid2).child("Friends-request").child(uid).removeValue();
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Toast.makeText(getContext(), error.getMessage(), Toast.LENGTH_SHORT).show();
}
}));
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Toast.makeText(getContext(), error.getMessage(), Toast.LENGTH_SHORT).show();
}
}));
viewHolder.del.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
isRef.child("Users").child(uid).child("Friends-request").child(uid2).removeValue();
isRef.child("Users").child(uid2).child("Friends-request").child(uid).removeValue();
}
});
// Return the completed view to render on screen
return convertView;
}
}
and here I call it in the activity on the listview:
private void getReqs() {
DatabaseReference isRef = FirebaseDatabase.getInstance().getReference().child("Users").child(uid).child("Friends-request");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (reqsTemp.size() > 0){reqsTemp.clear();}
for (DataSnapshot ds : snapshot.getChildren()){
addFriends reqs = ds.getValue(addFriends.class);
if (reqs!=null) {
reqsTemp.add(reqs);
}
}
reqsadapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Toast.makeText(Friends.this, error.getMessage(), Toast.LENGTH_SHORT).show();
}
};
isRef.addValueEventListener(valueEventListener);
}
by the way here is the element code from the adapter:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="96dp"
android:orientation="horizontal">
<androidx.cardview.widget.CardView
android:id="#+id/cardViewsdd"
android:layout_width="86dp"
android:layout_height="86dp"
android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
app:cardBackgroundColor="#color/common_google_signin_btn_text_dark_disabled"
app:cardCornerRadius="50dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/uImgreqs"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:src="#mipmap/ic_launcher_round"
android:contentDescription="#string/todo" />
</androidx.cardview.widget.CardView>
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="5dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="#+id/tvDescr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text=""
android:textSize="20sp" />
<TextView
android:id="#+id/tvPrice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="18dp"
android:text="" />
</LinearLayout>
<LinearLayout
android:layout_width="100dp"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="#+id/ibAdd"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="#android:drawable/ic_input_add" />
<ImageView
android:id="#+id/ibDel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="#drawable/ic_dialog_close_light" />
</LinearLayout>
</LinearLayout>
the add button should record the id of both users to each other, and del accordingly delete the request. uImgreqs is just a photo of the user, and both textviews are user data of the username, etc. If anything needs to be added, I will be glad to add, because I am in despair, and the deadlines are running out
God, boooooo well noooo. Android Studio, I adore you.
I found a solution, it turned out that the problem was due to (v ->, I or the studio translated the OnClick function into a lambda and because of this it returned a null object ... 3 and a half days ... I spent more than three days on this, omg
viewHolder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {});
No, it`s not win
uh, no, it didn't solve the problem completely and now throws an error on every imageView .setOnClicklistener ...
I found the problem, I misdated the label:
convertView = inflater.inflate(R.layout.friends_item, parent, false);
very unremarkable line, facepalm
I'm just trying to display all images uploaded to Firebase Storage using a recyclerview. Every time I run my app to test out everything my app crashes and when I check the Logcat it keeps telling me Attempt to invoke interface method 'int java.util.List.size()' on a null object reference at com.myapp.yoody.AdapterOne.getItemCount. I'm just wondering what is the null object its referring to. Is it talking about the fact that it's not connecting to firebase? or what is it? I've been trying for days to get this thing to work and I've got nothing. Please help me out here. I hope my question doesn't sound confusing. Here's my code below. Thanks in advance
//Profilepage (The page where the images are supposed to display)
FirebaseAuth firebaseAuth;
FirebaseUser firebaseUser;
TextView name;
DatabaseReference databaseReference;
StorageReference storageReference;
private Context mccontext=ProfileActivity.this;
RecyclerView recyclerView;
AdapterOne adapter1;
String uid;
// Folder path for Firebase Storage.
ImageView imageView;
//List<ImageUploadInfo> list=new ArrayList<>();
ArrayList<ImageUploadInfo> imagesList;
// Folder path for Firebase Storage.
String Storage_Path = "Images/";
// Root Database Name for Firebase Database.
public static final String Database_Path = "Images";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
recyclerView=findViewById(R.id.recyclerView);
LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
recyclerView.setHasFixedSize(true);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
overridePendingTransition(R.anim.slide_right, R.anim.slide_left);
adapter1=new AdapterOne(mccontext,imagesList);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(adapter1);
imagesList=new ArrayList<>();
adapter1.notifyDataSetChanged();
//databaseReference=FirebaseDatabase.getInstance().getReference("Users");
uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
// Assign FirebaseStorage instance to storageReference.
storageReference = FirebaseStorage.getInstance().getReference();
// Assign FirebaseDatabase instance with root database name.
databaseReference = FirebaseDatabase.getInstance().getReference(Database_Path);
// Adding Add Value Event Listener to databaseReference.
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot postSnapshot:dataSnapshot.getChildren() ){
ImageUploadInfo imageUploadInfo=postSnapshot.getValue(ImageUploadInfo.class);
imagesList.add(imageUploadInfo);
}
adapter1 = new AdapterOne(getApplicationContext(), imagesList);
recyclerView.setAdapter(adapter1);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
//My Adapter class
public class AdapterOne extends RecyclerView.Adapter<AdapterOne.ViewHolder> {
Context context;
List<ImageUploadInfo> imagesList;
public AdapterOne(Context c, List<ImageUploadInfo> TempList) {
imagesList = TempList;
context = c;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
ImageUploadInfo imageUploadInfo = imagesList.get(position);
Glide.with(context).load(imageUploadInfo.getImageUrl()).into(holder.imageView);
}
#Override
public int getItemCount() {
return imagesList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ImageView imageView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
imageView=(ImageView) itemView.findViewById(R.id.imageview);
}
}
}
//UploadInfo class
public class ImageUploadInfo {
// public String imageName;
public String imageURL;
public ImageUploadInfo() {} // default constructor that takes no arguments
public ImageUploadInfo( String url) {
this.imageURL= url;
}
public String getImageUrl() {
return imageURL;
}
public void setImageURL(String imageURL) {
this.imageURL = imageURL;
}
}
//CardView class
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:background="#color/white"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical"
>
<GridLayout
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_marginTop="0dp"
android:alignmentMode="alignMargins"
android:columnCount="1"
android:paddingTop="20dp"
android:columnOrderPreserved="false"
android:rowCount="3">
<!-- 3 -->
<!-- 4 -->
<androidx.cardview.widget.CardView
android:layout_width="350dp"
android:layout_height="320dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginLeft="6dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="10dp"
app:cardCornerRadius="0dp"
app:cardElevation="0dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:id="#+id/imageview"
/>
<!--
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/imagename"
android:text="Image Name"
/>
-->
</androidx.cardview.widget.CardView>
</GridLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
The problem is that you initialize the list AFTER you send it to adapter. So adapter trying to execute its method on the list which is not exist. Move init lane BEFORE send it in adapter
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I am trying to fetch data from firebase and put it into a recycler view through adapter. But, no data is being displayed.
My code in Main Activity:
DatabaseReference databaseReference;
RecyclerView recyclerView;
ArrayList<Menu> menuList;
EditMenuAdapter editMenuAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_menu);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
menuList = new ArrayList<Menu>();
databaseReference = FirebaseDatabase.getInstance().getReference().child("menu");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
Menu menu = dataSnapshot1.getValue(Menu.class);
menuList.add(menu);
}
editMenuAdapter = new EditMenuAdapter(EditMenuActivity.this, menuList);
recyclerView.setAdapter(editMenuAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(EditMenuActivity.this, "Something went wrong", Toast.LENGTH_LONG).show();
}
});
My adapter class:
public class EditMenuAdapter extends RecyclerView.Adapter<EditMenuAdapter.MyViewHolder> {
Context context;
ArrayList<Menu> menuArrayList;
public EditMenuAdapter(Context c, ArrayList<Menu> menus) {
context = c;
menuArrayList = menus;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.menu_list_layout, parent, false));
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
holder.dishNameTextView.setText(menuArrayList.get(position).getDishName());
holder.dishPriceTextView.setText(menuArrayList.get(position).getDishPrice());
}
#Override
public int getItemCount() {
return menuArrayList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView dishNameTextView;
TextView dishPriceTextView;
Switch dishActiveSwitch;
public MyViewHolder(View view) {
super(view);
dishNameTextView = (TextView) view.findViewById(R.id.dishNameTextView);
dishPriceTextView = (TextView) view.findViewById(R.id.dishPriceTextView);
dishActiveSwitch = (Switch) view.findViewById(R.id.dishActiveSwitch);
}
}
}
The layout resource file is:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".EditMenuActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="397dp"
android:layout_height="599dp"
android:layout_marginStart="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/doneButton"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginStart="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="15dp"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="20dp"
android:text="Done"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/recyclerView" />
The log shows: E/RecyclerView: No adapter attached; skipping layout. No data is displayed.
Only the switch is being displayed on the screen. Please help!
Create instance of adapter in onCreate and attach it to RV:
protected void onCreate(Bundle savedInstanceState) {
...
editMenuAdapter = new EditMenuAdapter(this, new ArrayList<>());
recyclerView.setAdapter(adapter);
...
}
In the response of Firebase onDataChange:
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
...
editMenuAdapter.setItems(menuList);
runOnUiThread(() -> editMenuAdapter.notifyDataSetChanged());
}
I am new to programming in androidstudio/java so I'm looking for some assistance. I'm currently trying to make an app that is similar to facebook messenger by using firebase and android studio. I'm at the stage where I am trying to create the layout for the ChatActivity (see code below). However, I'm having some issues with showing new messages at the bottom of the screen.
I have tried using ".setStackFromEnd(true);" but setting it either true or false, the text still appears at the top! (see images)
Code:
ChatActivity is as follows:
public class ChatActivity extends AppCompatActivity {
//Firebase variables
private FirebaseAuth mAuth;
private DatabaseReference mDatabaseUser, mDatabaseChat;
private FirebaseStorage mStorage;
private StorageReference mStorageReference;
//Recyclerview variables
private RecyclerView recyclerView;
private RecyclerViewChatAdapter mChatAdapter;
//Variables for users
private String userId,friendId,namefriend,chatId;
private CircleImageView mImageFriend;
private ArrayList<ChatObject> resultsChat = new ArrayList<>();
private Button mSendButton;
private EditText mSendText;
private TextView mNameFriend;
//Linear layout manager
private LinearLayoutManager mLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
//prevent opening keyboard automatically
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
//Set firebase variables
mAuth = FirebaseAuth.getInstance();
userId = mAuth.getCurrentUser().getUid();
friendId = getIntent().getExtras().getString("friendId");
namefriend = getIntent().getExtras().getString("friendName");
mDatabaseUser = FirebaseDatabase.getInstance().getReference().child("Friends").child(userId).child("Friendlist").child(friendId).child("chatId");
mDatabaseChat = FirebaseDatabase.getInstance().getReference();
mStorage = FirebaseStorage.getInstance();
mStorageReference = mStorage.getReference();
//Get findviewbyId's
recyclerView = (RecyclerView) findViewById(R.id.ChatActivity_recyclerview);
mSendButton = (Button) findViewById(R.id.ChatActivity_Send);
mSendText = (EditText) findViewById(R.id.ChatActivity_SendText);
mNameFriend = (TextView) findViewById(R.id.ChatActivity_Name);
mImageFriend = (CircleImageView) findViewById(R.id.ChatActivity_ImageFriend);
//Filling in recyclerview and adapter
FillInRecyclerView();
//Set name
mNameFriend.setText(" "+namefriend);
//set picture
StorageReference profileRef = mStorageReference.child("profilepictures/"+friendId);
GlideApp.with(this)
.load(profileRef)
.into(mImageFriend);
//Setting database for messages
getChatId();
//Send message
mSendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendMessage();
}
});
}
private void sendMessage() {
String sendMessageText = mSendText.getText().toString();
if(!sendMessageText.isEmpty()){
DatabaseReference newMessageDb = mDatabaseChat.push();
Map newMessage = new HashMap();
newMessage.put("createdByUser", userId);
newMessage.put("text", sendMessageText);
newMessageDb.setValue(newMessage);
}
mSendText.setText(null);
}
private void getChatId(){
mDatabaseUser.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
chatId = dataSnapshot.getValue().toString();
mDatabaseChat = mDatabaseChat.child("Message").child(chatId);
getChatMessages();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void getChatMessages() {
mDatabaseChat.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
if(dataSnapshot.exists()){
String message = null;
String createdByUser = null;
if (dataSnapshot.child("text").getValue()!=null){
message = dataSnapshot.child("text").getValue().toString();
}
if (dataSnapshot.child("createdByUser").getValue()!=null){
createdByUser = dataSnapshot.child("createdByUser").getValue().toString();
}
if(message!=null && createdByUser!=null){
Boolean currentUserBoolean = false;
if(createdByUser.equals(userId)){
currentUserBoolean=true;
}
ChatObject newMessage = new ChatObject(message, currentUserBoolean, createdByUser);
resultsChat.add(0,newMessage);
mChatAdapter.notifyDataSetChanged();
mLayoutManager.scrollToPositionWithOffset(0,0);
}
}
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
public void FillInRecyclerView(){
mLayoutManager = new LinearLayoutManager(this);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(true);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);
mLayoutManager.scrollToPositionWithOffset(0,0);
mChatAdapter = new RecyclerViewChatAdapter(ChatActivity.this, resultsChat);
recyclerView.setAdapter(mChatAdapter);
recyclerView.setLayoutManager(mLayoutManager);
}
ActivityChat XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ChatActivity">
<LinearLayout
android:id="#+id/ChatActivity_LinearLayoutHeader"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#drawable/background_chatheader"
android:paddingStart="7dp"
android:paddingLeft="7dp"
android:windowSoftInputMode="adjustResize"
android:layout_marginBottom="3dp">
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="45dp"
android:layout_height="45dp"
android:id="#+id/ChatActivity_ImageFriend"
android:src="#mipmap/ic_launcher"
android:layout_gravity="center"
/>
<TextView
android:id="#+id/ChatActivity_Name"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Test"
android:gravity="center_vertical|start"
android:textSize="25sp"
android:textColor="#color/white"
android:fontFamily="sans-serif"
/>
</LinearLayout>
<android.support.v4.widget.NestedScrollView
android:layout_below="#+id/ChatActivity_LinearLayoutHeader"
android:layout_above="#id/ChatActivity_LinearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
android:scrollbarStyle="outsideOverlay"
>
<android.support.v7.widget.RecyclerView
app:stackFromEnd="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/ChatActivity_LinearLayout"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
android:id="#+id/ChatActivity_recyclerview"
>
</android.support.v7.widget.RecyclerView>
</android.support.v4.widget.NestedScrollView>
<LinearLayout
android:id="#+id/ChatActivity_LinearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<EditText
android:layout_weight="0.7"
android:id="#+id/ChatActivity_SendText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="Type your message..."
/>
<Button
android:layout_weight="0.3"
android:id="#+id/ChatActivity_Send"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="send"/>
</LinearLayout>
</RelativeLayout>
Itemlayout xml file for the recyclerview:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/Recyclerview_Parent_Container"
>
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/Recyclerview_ChatImage"
android:layout_width="42dp"
android:layout_height="42dp"
android:src="#mipmap/ic_launcher"
android:visibility="invisible"
/>
<LinearLayout
android:layout_marginStart="9dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="6sp"
android:id="#+id/Recyclerview_Container"
android:orientation="horizontal"
android:background="#drawable/border_chat_bubbles"
android:layout_marginLeft="7dp"
android:layout_marginEnd="7dp">
<TextView
android:id="#+id/Recyclerview_Message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Text"
android:textSize="18sp"
/>
</LinearLayout>
</LinearLayout>
RecyclerView adapter code:
public class RecyclerViewChatAdapter extends RecyclerView.Adapter<RecyclerViewChatAdapter.ViewHolder> {
private List<ChatObject> chatList;
private Context context;
//Firebase
private FirebaseAuth mAuth;
private String CurrentUserId;
private FirebaseStorage mStorage;
private StorageReference mStorageReference;
public RecyclerViewChatAdapter(Context context, List<ChatObject> chatList) {
this.chatList = chatList;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recyclerview_chatlist_layout, viewGroup, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, final int position) {
//Firebase variables
mStorage = FirebaseStorage.getInstance();
mStorageReference = mStorage.getReference();
mAuth = FirebaseAuth.getInstance();
CurrentUserId = mAuth.getCurrentUser().getUid();
//Setting profile picture into recyclerview
StorageReference profileRef = mStorageReference.child("profilepictures/" + chatList.get(position).getUserid());
GlideApp.with(context)
.load(profileRef)
.into(holder.mProfilepicture);
//Setting message layout for user and friend
holder.mMessage.setText(chatList.get(position).getMessage());
if (chatList.get(position).getCurrentUser()) {
holder.mParentContainer.setGravity(Gravity.END);
holder.mMessage.setTextColor(Color.parseColor("#404040"));
holder.mContainer.setBackgroundResource(R.drawable.border_chat_bubbles);
holder.mProfilepicture.setVisibility(View.INVISIBLE);
} else {
holder.mParentContainer.setGravity(Gravity.START);
holder.mMessage.setTextColor(Color.parseColor("#FFFFFF"));
holder.mContainer.setBackgroundResource(R.drawable.border_chat_bubbles_friend);
holder.mProfilepicture.setVisibility(View.VISIBLE);
//Set picture of friend when multiple messages
int i = 1;
if(position+i<chatList.size()) {
while (!chatList.get(position + i).getCurrentUser()) {
if ((chatList.get(position + i).getCurrentUser()) == chatList.get(position).getCurrentUser()) {
holder.mProfilepicture.setVisibility(View.INVISIBLE);
i++;
} else {
break;
}
if (position + i == chatList.size()) {
break;
}
}
}
}
}
#Override
public int getItemCount() {
return this.chatList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView mMessage;
LinearLayout mContainer, mParentContainer;
CircleImageView mProfilepicture;
public ViewHolder(View itemView) {
super(itemView);
mParentContainer = itemView.findViewById(R.id.Recyclerview_Parent_Container);
mMessage = itemView.findViewById(R.id.Recyclerview_Message);
mContainer = itemView.findViewById(R.id.Recyclerview_Container);
mProfilepicture = itemView.findViewById(R.id.Recyclerview_ChatImage);
}
}
What it looks like on the emulator:
Screenshot of emulator of what it looks like
What I want it to look like:
Emulator of what I want
Now if I set SetStackFromEnd to true or false, I keep getting the same result as in the above picture. However, SetReverseLayout does work! What also does not work is the scrollToPositionWithOffset(0,0); or any other variation, I think the issue must be linked to each other
What have I tried to do already and did not work:
changing the position at what time "FillInRecyclerView()" method is being called, however this did not change anything.
Various combinations of SetReverseLayout/SetStackFromEnd to true
Setting stackfromend to true in the XML code
Changing the RelativeLayout to a LinearLayout in 'ChatActivity.xml'
Setting the relative layout height to match parent
Any help is welcome!
Thank you
You need to use both setStackFromEnd and setReverseLayout. Set both value true and you will get your expected output.
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(mContext);
recyclerView.setLayoutManager(mLinearLayoutManager);
mLinearLayoutManager.setStackFromEnd(true);
mLinearLayoutManager.setReverseLayout(true);
Left is Mary and right is Bill , the speaker's textView will show on the right side , the situation is that Mary says 1 and 2 , it looks fine , just like the photo:
next step : the right side device is Bill who says a and b , it looks fine that is just what i want.
when they type words more and more , my issue is happen like this:
But when i leave the ChatGroup1 and enter it again , it looks fine
So my issue is that it has something wrong with realtime on display recyclerView
How can i fix this issue , i try to add listData.clear(); , it's not working
Any help would be appreciated , thanks in advance .
It's my chat channel layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerChat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/button2">
</android.support.v7.widget.RecyclerView>
<Button
android:id="#+id/button2"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:background="#drawable/ic_send" />
<EditText
android:gravity="center"
android:hint="Type your message..."
android:background="#drawable/edit_corner"
android:id="#+id/editText2"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_toLeftOf="#+id/button2"
android:layout_toStartOf="#+id/button2" />
</RelativeLayout>
it's my chat class for Firebase and recyclerView:
//global variable
private RecyclerView recyclerChat;
private ArrayList<ChatItem> listData = new ArrayList<>();
private RecyclerChatItemAdapter adapter;
private DatabaseReference root;
About FirebaseDatabase:
root = FirebaseDatabase.getInstance().getReference().child(room_name);
//send message to FirebaseDatabase
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Map<String, Object> map = new HashMap<>();
temp_key = root.push().getKey();
root.updateChildren(map);
DatabaseReference message_root = root.child(temp_key);
Map<String, Object> map2 = new HashMap<>();
map2.put("name", user_name);
map2.put("msg", editText2.getText().toString());
message_root.updateChildren(map2);
manager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken() , InputMethodManager.HIDE_NOT_ALWAYS);//just hide the keyboard when send message
editText2.setText("");
}
});
I think that may be my issue is just right here , about my recyclerView:
root.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
ChatItem chatItem = dataSnapshot.getValue(ChatItem.class);//put the data to my javabean from Firebase
Log.d("Contacts: ", chatItem.toString());
listData.add(chatItem);
recyclerChat.scrollToPosition(adapter.getItemCount() - 1);//just let the latest data below
adapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
//append_right_chat_conversation(dataSnapshot);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
LinearLayoutManager manager = new LinearLayoutManager(this);
// GridLayoutManager gridLayoutManager=new GridLayoutManager(this,2);
manager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerChat.setLayoutManager(manager);
adapter = new RecyclerChatItemAdapter(this, listData);
recyclerChat.setAdapter(adapter);
adapter.notifyDataSetChanged();//when i leave the chat group and enter again , it looks fine because this.
It's my recyclerView adapter:
public class RecyclerChatItemAdapter extends RecyclerView.Adapter<RecyclerChatItemAdapter.MyViewHolder>{
private Context context;
private List<ChatItem> mDatas;
public RecyclerChatItemAdapter(Context context, List<ChatItem> mDatas) {
this.context = context;
this.mDatas = mDatas;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view=View.inflate(parent.getContext(),R.layout.for_chat_item_layout,null);
MyViewHolder myViewHolder=new MyViewHolder(view);
return myViewHolder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
String myName=mDatas.get(position).getName();
Contacts contacts=Contacts.getContacts();
String createName=contacts.getName();
if (myName.equals(createName)){
holder.textRight.setText(mDatas.get(position).getMsg()+"("+mDatas.get(position).getName()+")");
holder.textRight.setTextColor(Color.BLUE);
holder.textRight.setBackground(context.getResources().getDrawable(R.drawable.chat_green));
}else {
holder.textLeft.setText(mDatas.get(position).getMsg()+"("+mDatas.get(position).getName()+")");
holder.textLeft.setTextColor(Color.RED);
holder.textLeft.setBackground(context.getResources().getDrawable(R.drawable.chat_blue));
}
}
#Override
public int getItemCount() {
return mDatas.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder{
private TextView textLeft,textRight;
public MyViewHolder(View itemView) {
super(itemView);
textLeft=(TextView)itemView.findViewById(R.id.textLeft);
textRight=(TextView)itemView.findViewById(R.id.textRight);
}
}
}
You don't have shown Adapter layout and adapter code... It can be visibility problem of view.
You may be set visibility for view.. So for that please ensure that you have written something like this..
if (myName.equals(createName)){
holder.textRight.setVisibility(VISIBLE);
holder.textLeft.setVisibility(GONE);
holder.textRight.setText(mDatas.get(position).getMsg()+"("+mDatas.get(position).getName()+")");
holder.textRight.setTextColor(Color.BLUE);
holder.textRight.setBackground(context.getResources().getDrawable(R.drawable.chat_green));
}else {
holder.textRight.setVisibility(GONE);
holder.textLeft.setVisibility(VISIBLE);
holder.textLeft.setText(mDatas.get(position).getMsg()+"("+mDatas.get(position).getName()+")");
holder.textLeft.setTextColor(Color.RED);
holder.textLeft.setBackground(context.getResources().getDrawable(R.drawable.chat_blue));
}