Error to load item with RecyclerView

本秂侑毒 提交于 2020-01-16 19:42:07

问题


I know that RecyclerView loads the items again every time to save memory and increase performance. However, I found a problem with the images, that is that when I start to scroll quickly the recyclerView the elements start to recharge in the wrong order. I put the video in description of what happens. How can I resolve this error?

LINK: https://www.youtube.com/watch?v=iwHUYgWIm5g

RecyclerViewAdapter.class

    package com.example.mattiaferigutti.chatjava;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.squareup.picasso.Picasso;

import java.io.IOException;
import java.util.List;

public class RecyclerMessegeAdapter extends RecyclerView.Adapter<RecyclerMessegeAdapter.MyViewHolder> {

    private List<Message> messages;
    private FirebaseAuth mAuth;
    private StorageReference storageRef;
    private Context mContext;


    public RecyclerMessegeAdapter(List<Message> messages, Context context) {
        this.messages = messages;
        this.mContext = context;
        mAuth = FirebaseAuth.getInstance();
        storageRef = FirebaseStorage.getInstance().getReference();
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.message_single_layout,
                null, false);
        return new MyViewHolder(v);
    }

    @Override
    public void onBindViewHolder(@NonNull final MyViewHolder myViewHolder, int i) {

        String currentUserId = mAuth.getUid();

        Message currentMessage = messages.get(i);

        String fromUser = currentMessage.getMessageUser();

        if (fromUser.equals(currentUserId) && currentMessage.getMessageType().equals("text")) {
            myViewHolder.textView.setBackgroundResource(R.drawable.message_text_background);
            myViewHolder.textView.setTextColor(Color.WHITE);
            myViewHolder.imageView.setVisibility(View.GONE);

            myViewHolder.textView.setText(currentMessage.getMessageText());

        } else if (currentMessage.getMessageType().equals("text")) {
            myViewHolder.textView.setBackgroundResource(R.drawable.message_text_background);
            myViewHolder.textView.setBackgroundColor(Color.WHITE);
            myViewHolder.textView.setTextColor(Color.BLACK);
            myViewHolder.imageView.setVisibility(View.GONE);

            myViewHolder.textView.setText(currentMessage.getMessageText());

        } else if (currentMessage.getMessageType().equals("image")) {
            myViewHolder.textView.setVisibility(View.GONE);

            String url = currentMessage.getMessageText();

            storageRef.child("message_image/" + url + ".jpg").getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                @Override
                public void onSuccess(Uri uri) {

                    Picasso.get()
                            .load(uri)
                            .into(myViewHolder.imageView);
                    myViewHolder.imageView.setVisibility(View.VISIBLE);
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception exception) {
                    // Handle any errors
                }
            });

        }
    }

    //TODO: mettere il testo a destra o a sinistra

    @Override
    public int getItemCount() {
        return messages.size();
    }

    static class MyViewHolder extends RecyclerView.ViewHolder {

        private TextView textView;
        private ImageView imageView;
        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.message);
            imageView = itemView.findViewById(R.id.imageView);
        }
    }
}

MainActivity.class

    package com.example.mattiaferigutti.chatjava;

import android.content.Intent;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.ChildEventListener;
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 com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private static final int GALLERY_PICK = 123;
    //Firebase
    private FirebaseAuth mAuth;
    private DatabaseReference myRef;

    //Storage Firebase
    private StorageReference mImageStorage;

    private Toolbar mToolbar;
    private String mCurrentUserId;
    private EditText mTextInput;
    private Button mSendBtn;
    private ImageButton mPlusBtn;
    private RecyclerView mMessagesList;
    private final List<Message> messages = new ArrayList<>();
    private RecyclerMessegeAdapter mAdapter;

    private String usersDentist = "aaXmkFhvrUWmuzC6GDZAV8a0i0u1";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mAuth = FirebaseAuth.getInstance();
        myRef = FirebaseDatabase.getInstance().getReference();
        mImageStorage = FirebaseStorage.getInstance().getReference();

        mToolbar = findViewById(R.id.main_page_toolbar);
        mSendBtn = findViewById(R.id.sendButton);
        mTextInput = findViewById(R.id.textEdit);
        mMessagesList = findViewById(R.id.recyclerView);
        mPlusBtn = findViewById(R.id.plusBtn);

        setSupportActionBar(mToolbar);
        getSupportActionBar().setTitle("Chat");

        if (mAuth.getCurrentUser() != null)
        mCurrentUserId = mAuth.getCurrentUser().getUid();

        mAdapter = new RecyclerMessegeAdapter(messages, this);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        mMessagesList.setLayoutManager(layoutManager);
        mMessagesList.isAttachedToWindow();
        mMessagesList.setAdapter(mAdapter);

        if (mAuth.getCurrentUser() != null)
        loadMessages();

        mMessagesList.scrollToPosition(messages.size()-1);

        mSendBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String textSend = mTextInput.getText().toString();
                long currentMillis = System.currentTimeMillis();

                myRef.child("messages").child(mCurrentUserId).child(usersDentist).push().setValue(new Message(
                        textSend, currentMillis, mCurrentUserId, "text"
                ));


                myRef.child("messages").child(usersDentist).child(mCurrentUserId).push().setValue(new Message(
                        textSend, currentMillis, mCurrentUserId, "text"
                ));


                mTextInput.setText("");
            }
        });


        mPlusBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent galleryIntent = new Intent();
                galleryIntent.setType("image/*");
                galleryIntent.setAction(Intent.ACTION_GET_CONTENT);

                startActivityForResult(Intent.createChooser(galleryIntent, "SELECT IMAGE"),
                        GALLERY_PICK);
            }
        });

    }

    private void loadMessages() {
        myRef.child("messages").child(mCurrentUserId).child(usersDentist).addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                //messages.clear();

                Message message = dataSnapshot.getValue(Message.class);
                messages.add(message);

                /*if (messages.size() > 0) {
                    final LinearLayoutManager manager = new LinearLayoutManager(MainActivity.this);
                    mMessagesList.setLayoutManager(manager);
                    mAdapter = new RecyclerMessegeAdapter(messages, MainActivity.this);
                    mMessagesList.setAdapter(mAdapter);
                    mAdapter.notifyDataSetChanged();
                }*/

                mAdapter.notifyDataSetChanged();

            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                mAdapter.notifyDataSetChanged();
            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {
                mAdapter.notifyDataSetChanged();
            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
    }


    @Override
    public void onStart() {
        super.onStart();
        // Check if user is signed in (non-null) and update UI accordingly.
        FirebaseUser currentUser = mAuth.getCurrentUser();

        if (currentUser == null) {
            sendToStart();
        }
    }

    private void sendToStart() {
        Intent startActivity = new Intent(MainActivity.this, StartActivity.class);
        startActivity(startActivity);
        finish();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.main_menu, menu);

        return super.onCreateOptionsMenu(menu);
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case R.id.account_settings:
                break;

            case R.id.all_users:
                break;

            case R.id.log_out:
                FirebaseAuth.getInstance().signOut();
                sendToStart();
                break;
        }

        return super.onOptionsItemSelected(item);
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == GALLERY_PICK && resultCode == RESULT_OK) {
            Uri image = data.getData();

            long currentMillis = System.currentTimeMillis();

            final String pushId = String.valueOf(myRef.push());

            myRef.child("messages").child(mCurrentUserId).child(usersDentist).push().setValue(new Message(
                    pushId, currentMillis, mCurrentUserId, "image"
            ));

            myRef.child("messages").child(usersDentist).child(mCurrentUserId).push().setValue(new Message(
                    pushId, currentMillis, mCurrentUserId, "image"
            ));


            StorageReference filePath = mImageStorage.child("message_image").child(pushId + ".jpg");
            filePath.putFile(image).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {
                    if (task.isSuccessful()) {
                        Toast.makeText(getApplicationContext(), "succeful", Toast.LENGTH_SHORT).show();
                        mAdapter.notifyDataSetChanged();
                    }
                }
            });
        }


    }
}

回答1:


Just make your TextView visible if message type is text.

Add myViewHolder.textView.setVisibility(View.VISIBLE);




回答2:


Replace Picasso Part Code with this example:

Picasso.get()
.load(url) // url of the image
.placeholder(R.drawable.user_placeholder) //ur place holder image it could be any image
.error(R.drawable.user_placeholder_error) // optional if image is not loaded
.into(imageView); // ur image view

For ur case it is like :

myViewHolder.imageView.setVisibility(View.VISIBLE);

Picasso.get()
    .load(uri) // url of the image
    .placeholder(R.mipmap.ic_launcher) //ur place holder image it could be any image
    .into(myViewHolder.imageView);



回答3:


https://github.com/QuickBlox/ChatMessagesAdapter-android

ChatMessagesAdapter for Android

QuickBlox simple to use UI library for showing quickblox chat messages inside android application.

Features

Ready-to-go QBChatMessage view adapter with a set of view types.
UI customisation for all message types.
Flexibility in improving and extending functionality.
Easy to connect with Quickblox.
Optimised and performant.
Flexible mechanism for styling layout for chat messages.
Add custom widgets inside predefined layout.

this may help



来源:https://stackoverflow.com/questions/52002356/error-to-load-item-with-recyclerview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!