Android 使用RecyclerView加载项目时出错

Android 使用RecyclerView加载项目时出错,android,firebase,firebase-realtime-database,android-recyclerview,Android,Firebase,Firebase Realtime Database,Android Recyclerview,我知道RecyclerView每次都会重新加载这些项目,以节省内存并提高性能。然而,我发现图像有一个问题,那就是当我开始快速滚动recyclerView时,元素开始以错误的顺序充电。我把视频放在描述发生了什么的地方。如何解决此错误 链接: RecycleServiceAdapter.class package com.example.mattiaferigutti.chatjava; import android.content.Context; import android.grap

我知道RecyclerView每次都会重新加载这些项目,以节省内存并提高性能。然而,我发现图像有一个问题,那就是当我开始快速滚动recyclerView时,元素开始以错误的顺序充电。我把视频放在描述发生了什么的地方。如何解决此错误

链接:

RecycleServiceAdapter.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);
        }
    }
}
package com.example.mattiaferigutti.chatjava;
导入android.content.Context;
导入android.graphics.Bitmap;
导入android.graphics.Color;
导入android.net.Uri;
导入android.provider.MediaStore;
导入android.support.annotation.NonNull;
导入android.support.v7.widget.RecyclerView;
导入android.view.LayoutInflater;
导入android.view.view;
导入android.view.ViewGroup;
导入android.widget.ImageView;
导入android.widget.TextView;
导入com.google.android.gms.tasks.OnFailureListener;
导入com.google.android.gms.tasks.OnSuccessListener;
导入com.google.firebase.auth.FirebaseAuth;
导入com.google.firebase.storage.firebase存储;
导入com.google.firebase.storage.StorageReference;
导入com.squareup.picasso.picasso;
导入java.io.IOException;
导入java.util.List;
公共类RecyclerAssegeAdapter扩展了RecyclerView.Adapter{
私人列表消息;
私人消防队;
私有存储引用storageRef;
私有上下文;
public RecyclerAssegeAdapter(列出消息、上下文){
this.messages=消息;
this.mContext=上下文;
mAuth=FirebaseAuth.getInstance();
storageRef=FirebaseStorage.getInstance().getReference();
}
@非空
@凌驾
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup ViewGroup,int i){
视图v=LayoutInflater.from(viewGroup.getContext())。充气(R.layout.message\u single\u布局,
空,假);
返回新的MyViewHolder(v);
}
@凌驾
public void onBindViewHolder(@NonNull final MyViewHolder MyViewHolder,int i){
字符串currentUserId=mAuth.getUid();
Message currentMessage=messages.get(i);
字符串fromUser=currentMessage.getMessageUser();
if(fromUser.equals(currentUserId)&¤tMessage.getMessageType().equals(“文本”)){
myViewHolder.textView.setBackgroundResource(R.drawable.message\u text\u background);
myViewHolder.textView.setTextColor(Color.WHITE);
myViewHolder.imageView.setVisibility(View.GONE);
myViewHolder.textView.setText(currentMessage.getMessageText());
}else if(currentMessage.getMessageType()等于(“文本”)){
myViewHolder.textView.setBackgroundResource(R.drawable.message\u text\u 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()等于(“图像”)){
myViewHolder.textView.setVisibility(View.GONE);
字符串url=currentMessage.getMessageText();
storageRef.child(“message_image/”+url+“.jpg”).getDownloadUrl().addOnSuccessListener(新的OnSuccessListener()){
@凌驾
成功时的公共无效(Uri){
毕加索
.load(uri)
.into(myViewHolder.imageView);
myViewHolder.imageView.setVisibility(View.VISIBLE);
}
}).addOnFailureListener(新的OnFailureListener(){
@凌驾
public void onFailure(@NonNull异常){
//处理任何错误
}
});
}
}
//TODO:mettere il testo a destra o a SINSTRIA
@凌驾
public int getItemCount(){
返回消息。size();
}
静态类MyViewHolder扩展了RecyclerView.ViewHolder{
私有文本视图文本视图;
私人影像视图;
公共MyViewHolder(@NonNull View itemView){
超级(项目视图);
textView=itemView.findViewById(R.id.message);
imageView=itemView.findViewById(R.id.imageView);
}
}
}
主课

    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();
                    }
                }
            });
        }


    }
}
package com.example.mattiaferigutti.chatjava;
导入android.content.Intent;
导入android.net.Uri;
导入android.support.annotation.NonNull;
导入android.support.annotation.Nullable;
导入android.support.v7.app.AppActivity;
导入android.os.Bundle;
导入android.support.v7.widget.LinearLayoutManager;
导入android.support.v7.widget.RecyclerView;
导入android.support.v7.widget.Toolbar;
导入android.view.Menu;
导入android.view.MenuItem;
导入android.view.view;
导入android.widget.Button;
导入android.widget.EditText;
导入android.widget.ImageButton;
导入android.widget.LinearLayout;
导入android.widget.Toast;
导入com.google.android.gms.tasks.OnCompleteListener;
导入com.google.android.gms.tasks.Task;
导入com.google.firebase.auth.FirebaseAuth;
导入com.google.firebase.auth.FirebaseUser;
导入com.google.firebase.database.ChildEventListener;
导入com.google.firebase.database.DataSnapshot;
导入com.google.firebase.database.DatabaseError;
导入com.google.firebase.database.DatabaseReference;
导入com.google.firebase.database.FirebaseDatabase;
导入com.google.firebase.database.ValueEventListener;
导入com.google.firebase.storage.firebase存储;
导入com.google.firebase.storage.StorageReference;
导入com.google.firebase.storage.UploadTask;
导入java.util.ArrayList;
导入java.util.List;
公共类MainActivity扩展了AppCompatActivity{
专用静态最终整型库_PICK=123;
//火基
私人消防队;
私有数据库参考myRef;
//仓库火灾
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
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);
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.