我最近遇到了一个问题。问题是当使用排序的RealmResults作为RealmRecyclerViewAdapter的源时, 如果添加了2个以上的项目,则添加的第一个项目会覆盖部分先前(中间项目)。 我知道这听起来很模糊,我很困惑,试图理解它好几天,但还没有找到解决方案,甚至没有解释。
初始化代码
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
mAttachmentDataSource = realm.where(Attachment.class).equalTo("parentId", presenter.getId()).findAllSorted("order", Sort.DESCENDING);
mAttachmentAdapter = new AttachmentAdapter(getActivity(), mAttachmentDataSource);
mAttachmentListManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
mAttachmentListView.setLayoutManager(mAttachmentListManager);
mAttachmentListView.setAdapter(mAttachmentAdapter);
...
}
适配器代码:
public class AttachmentAdapter extends RealmRecyclerViewAdapter<Attachment, AttachmentAdapter.ViewHolder> {
private Context mContext;
public boolean mReadOnly;
private int limit;
public void setLimit(int limit) {
this.limit = limit;
}
public AttachmentAdapter(Context context, @NonNull OrderedRealmCollection<Attachment> attachments) {
super(attachments, true);
initialize(context, false);
}
public AttachmentAdapter(Context context, @NonNull OrderedRealmCollection<Attachment> attachments, boolean readonly) {
super(attachments, true);
initialize(context, readonly);
}
private void initialize(Context context, boolean readonly) {
setHasStableIds(true);
mContext = context;
mReadOnly = readonly;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the custom layout
View contactView = inflater.inflate(R.layout.item_attachment, parent, false);
// Return a new holder instance
return new ViewHolder(contactView);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (getData() == null) return;
holder.mThumbFileIconImageView.setVisibility(View.GONE);
if (position == 0 && !mReadOnly) {
holder.mRemoveIconView.setVisibility(View.GONE);
holder.mThumbnailView.setBackground(ActivityCompat.getDrawable(mContext,
R.drawable.dashed_accented_no_border));
RxUtils.clicks(holder.mThumbnailView)
.subscribe(v -> openAttachmentSelection());
holder.itemView.setVisibility(limit == getItemCount() - 1 ? View.GONE : View.VISIBLE);
} else {
Attachment model = getData().get(position);
long id = model.getId();
holder.initialize(id, model.getParentId());
holder.mRemoveIconView.setVisibility(mReadOnly ? View.GONE : View.VISIBLE);
holder.mRemoveIconView.setTag(id);
MediaType mediaType = MediaType.parse(model.getMimeType());
String path = model.getAbsoluteFilePath();
if (mediaType != null && mediaType.is(MediaType.ANY_IMAGE_TYPE)) {
if (path != null) {
Glide.with(mContext)
.fromString()
.load(path)
.listener(new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e, String s, Target<GlideDrawable> target, boolean b) {
holder.mProgressBar.setVisibility(View.GONE);
return false;
}
@Override
public boolean onResourceReady(GlideDrawable glideDrawable, String s, Target<GlideDrawable> target, boolean b, boolean b1) {
holder.mProgressBar.setVisibility(View.VISIBLE);
return false;
}
})
.centerCrop()
.crossFade()
.thumbnail(0.1f)
.into(holder.mThumbnailView);
} else if (model.data != null) {
Glide.with(mContext)
.fromBytes()
.load(model.data)
.listener(new RequestListener<byte[], GlideDrawable>() {
@Override
public boolean onException(Exception e, byte[] bytes, Target<GlideDrawable> target, boolean b) {
holder.mProgressBar.setVisibility(View.GONE);
return false;
}
@Override
public boolean onResourceReady(GlideDrawable glideDrawable, byte[] bytes, Target<GlideDrawable> target, boolean b, boolean b1) {
holder.mProgressBar.setVisibility(View.VISIBLE);
return false;
}
})
.centerCrop()
.crossFade()
.thumbnail(0.1f)
.into(holder.mThumbnailView);
}
} else {
int icon = AttachmentUtils.getAttachmentIcon(mediaType);
holder.mThumbFileIconImageView.setVisibility(View.VISIBLE);
holder.mThumbFileIconImageView.setImageResource(icon);
}
holder.mOverlayView.setVisibility(View.INVISIBLE);
holder.mThumbnailView.setOnClickListener(e -> holder.openGallery(mContext));
holder.mRemoveIconView.setOnClickListener(e -> holder.remove());
}
}
@Override
public int getItemCount() {
return getData().size();
}
public void openAttachmentSelection() {
new MaterialDialog.Builder(mContext)
.title(mContext.getText(R.string.selectAttachment))
.backgroundColorRes(R.color.white)
.contentColorRes(R.color.black)
.titleColorRes(R.color.black)
.items(R.array.select_attachment_types)
.itemsCallbackSingleChoice(-1, (dialog, view, which, text) -> {
switch (which) {
case 0:
CameraUtils.returnPicture((AppCompatActivity) mContext);
break;
case 1:
getAttachmentImageFile();
break;
case 2:
getAttachmentFile();
break;
}
return true;
})
.show();
}
private void getAttachmentImageFile() {
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.MEDIA_CONTENT_CONTROL) == PackageManager.PERMISSION_GRANTED) {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI);
intent.setType("image/*");
intent.putExtra("return-data", true);
((AppCompatActivity) mContext).startActivityForResult(intent, RequestCodes.REQUEST_IMAGE_SELECT);
return;
}
ActivityCompat.requestPermissions(((AppCompatActivity) mContext),
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
RequestCodes.REQUEST_PERMISSION_IMAGE
);
}
private void getAttachmentFile() {
// Create the ACTION_GET_CONTENT Intent
Intent getContentIntent = FileUtils.createGetContentIntent();
Intent intent = Intent.createChooser(getContentIntent, mContext.getString(R.string.attachment_list_select_file));
((AppCompatActivity) mContext).startActivityForResult(intent, RequestCodes.RESULT_FILE_SELECTED);
}
public class ViewHolder extends RecyclerView.ViewHolder {
private AttachmentPresenter presenter;
@BindView(R.id.item_attachment_thumbnail_overlay)
AppCompatImageView mOverlayView;
@BindView(R.id.item_attachment_thumbnail_layout)
FrameLayout mFrameLayout;
@BindView(R.id.item_attachment_thumbnail)
AppCompatImageView mThumbnailView;
@BindView(R.id.item_attachment_close_button)
AppCompatImageView mRemoveIconView;
@BindView(R.id.item_attachment_thumbnail_file_icon)
AppCompatImageView mThumbFileIconImageView;
@BindView(R.id.item_attachment_progress_bar)
ProgressBar mProgressBar;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public void initialize(long id, long parentId) {
if(this.presenter == null) this.presenter = new AttachmentPresenter();
this.presenter.initialize(id, parentId);
}
public void openGallery(Context mContext) {
AppCompatActivity activity = ((AppCompatActivity) mContext);
Attachment attachment = this.presenter.getAttachment();
;
if (attachment == null || activity == null) return;
FragmentTransaction fragmentTransaction = activity.getSupportFragmentManager().beginTransaction();
Fragment fragment = activity.getSupportFragmentManager().findFragmentByTag(AttachmentDialogFragment.FRAGMENT_TAG);
if (fragment != null) {
fragmentTransaction.remove(fragment);
}
fragmentTransaction.addToBackStack(null);
// Create and show the dialog.
AttachmentDialogFragment newFragment = AttachmentDialogFragment.newInstance(
attachment.getParentId(),
attachment.getId()
);
newFragment.show(fragmentTransaction, AttachmentDialogFragment.FRAGMENT_TAG);
}
public void remove() {
this.presenter.remove();
this.presenter.unbind();
this.presenter = null;
}
}
}
如何添加附件:
@Override
public void addAttachment(Bitmap image) {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File file = ImageUtils.saveToFile(image, "attachment_" + mId + "_" + timeStamp, context);
Realm realm = Realm.getDefaultInstance();
String mimeType = FileUtils.getMimeType(file);
realm.executeTransactionAsync(t -> {
long id = getId();
Attachment attachment = Attachment.create(t, Opportunity.class, id);
attachment.setAbsoluteFilePath(file.getAbsolutePath());
attachment.setMimeType(mimeType);
t.copyToRealmOrUpdate(attachment);
});
realm.close();
}
@Override
public void addAttachment(Uri uri) {
File file;
String absolutePath = null;
String mimeType = FileUtils.getMimeType(context, uri);
String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
try {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
file = File.createTempFile(
"attachment_" + mId + "_" + timeStamp , /* prefix */
"." + extension, /* suffix */
context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) /* directory */
);
File tempFile = new File(ImageUtils.getPath(uri, context));
GeneralUtils.copy(tempFile, file);
absolutePath = file.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
}
Realm realm = Realm.getDefaultInstance();
final String path = absolutePath;
realm.executeTransactionAsync(t -> {
long id = getId();
Attachment attachment = Attachment.create(t, Opportunity.class, id);
attachment.setAbsoluteFilePath(path);
attachment.setMimeType(mimeType);
t.copyToRealmOrUpdate(attachment);
for (Attachment a:t.where(Opportunity.class).findFirst().getAttachments()
) {
a.setCreatedAt(new Date());
}
});
realm.close();
}
我遇到的奇怪行为是:
将一张可爱的猫咪图片作为附件添加后:
添加另一个后(注意第一个被推到右边,添加的一个是按钮之前):
添加另一张图片后,第一张图片替换了前一张图片
起初我以为它的回收不正确,但无法确定究竟发生了什么。 奇怪的是 - 如果我根本不使用排序而只使用 .findAll()而不是 .findAllSorted(“order”,Sort.DESCENDING)一切正常,但添加的图像不会放在别人面前(这是我的目标)。