Я знаю, что RecyclerView загружает элементы снова каждый раз, чтобы сэкономить память и повысить производительность. Однако я обнаружил проблему с изображениями, заключающуюся в том, что, когда я начинаю быстро прокручивать программу повторного просмотра, элементы начинают перезаряжаться в неправильном порядке. Я поместил видео в описании того, что происходит. Как я могу устранить эту ошибку?
ССЫЛКА: 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();
}
}
});
}
}
}