gpt4 book ai didi

android - 实时数据列表 - 适配器不使用 DiffUtil 方法更新

转载 作者:行者123 更新时间:2023-11-29 02:36:23 27 4
gpt4 key购买 nike

我是 Android 的新手,我正在尝试使用新架构组件实现条码阅读器场景。

每次读取条码时,如果条码不在列表中,我想更新 ViewModel 中的列表,添加新元素,否则增加数量。

以下解决方案有效,但我对在适配器上调用“notifyDataSetChanged”以更新 UI 并不满意。这是因为 ViewModel 列表和适配器内部列表包含对相同对象的引用,因此 DiffUtil 不会捕获任何更改。

是否有更好的更新 UI 的方法?除了适配器之外,我还应该考虑进行任何改进来处理架构组件吗?

View 模型

public class ScannerViewModel extends ViewModel {

private MutableLiveData<List<ProductScan>> scanListLD;

public ScannerViewModel() {
scanListLD = new MutableLiveData<>();
scanListLD.setValue(new ArrayList<ProductScan>());
}

public LiveData<List<ProductScan>> getScanList() {
return scanListLD;
}

public void addBarcode(String barcode) {
List<ProductScan> list = scanListLD.getValue();
ProductScan scan = null;
for (ProductScan item : list) {
if (item.barcode.equals(barcode)) {
scan = item;
break;
}
}
if (scan == null) {
scan = new ProductScan();
scan.barcode = barcode;
scan.qt = 0;
list.add(scan);
}
scan.qt += 1;

scanListLD.postValue(list);
}
}

适配器

public class ScannerAdapter extends RecyclerView.Adapter<ScannerAdapter.ViewHolder> {

private List<ProductScan> scans;

public interface OnItemClickListener {
void onItemClick();
}

public ScannerAdapter(List<ProductScan> scans) {
this.scans = scans;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.template_scan, parent, false);
ScannerAdapter.ViewHolder viewHolder = new ScannerAdapter.ViewHolder(view);
return viewHolder;
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bindData(scans.get(position), position);
}

@Override
public int getItemCount() {
return scans != null ? scans.size() : 0;
}

//Not used since scans and newScans contain same objects
public void setScans(final List<ProductScan> newScans) {
if (scans == null) {
scans = new ArrayList<ProductScan>();
scans.addAll(newScans);
notifyItemRangeInserted(0, newScans.size());
} else {
DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
@Override
public int getOldListSize() {
return scans != null ? scans.size() : 0;
}

@Override
public int getNewListSize() {
return newScans != null ? newScans.size() : 0;
}

@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
ProductScan oldScan = scans.get(oldItemPosition);
ProductScan newScan = newScans.get(newItemPosition);
return Utils.equals(oldScan.barcode,newScan.barcode);
}

@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
ProductScan oldScan = scans.get(oldItemPosition);
ProductScan newScan = newScans.get(newItemPosition);
return Utils.equals(newScan.barcode, oldScan.barcode)
&& Utils.equals(newScan.productId, oldScan.productId)
&& Utils.equals(newScan.productDescription, oldScan.productDescription)
&& Utils.equals(newScan.qt, oldScan.qt);
}
});
scans.clear();
scans.addAll(newScans);
result.dispatchUpdatesTo(this);
}
}

public class ViewHolder extends RecyclerView.ViewHolder {

private TemplateScanBinding binding;

public ViewHolder(View itemView) {
super(itemView);
binding = DataBindingUtil.bind(itemView);
}

public void bindData(ProductScan scan, int position) {
binding.setScan(scan);
binding.setBtnIncreaseQtListener(() -> {
scan.qt += 1;
notifyItemChanged(position);
});
binding.setBtnDecreaseQtListener(() -> {
scan.qt = Math.max(1, scan.qt - 1);
notifyItemChanged(position);
});
binding.edtQt.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
if (i == EditorInfo.IME_ACTION_DONE) {
binding.edtQt.clearFocus();
}
return false;
}
});
binding.edtQt.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (scan.qt == null || scan.qt < 1) {
scan.qt = 1;
notifyItemChanged(position);
}
InputMethodManager imm = (InputMethodManager) binding.getRoot().getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
});
}
}
}

Activity

public class ScannerActivity extends ScannerBaseActivity {

@Inject
ViewModelFactory viewModelFactory;
private ScannerViewModel viewModel;

private ActivityScannerBinding binding;
private ScannerAdapter adapter;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

((MyApplication) getApplication()).getComponent().inject(this);
viewModel = ViewModelProviders.of(this, viewModelFactory).get(ScannerViewModel.class);
binding = DataBindingUtil.setContentView(this, R.layout.activity_scanner);

adapter = new ScannerAdapter(viewModel.getScanList().getValue());
binding.recvScans.setLayoutManager(new LinearLayoutManager(this));
binding.recvScans.setAdapter(adapter);
viewModel.getScanList().observe(this, (list) -> {
adapter.notifyDataSetChanged();
});

binding.btnScan.setOnClickListener((v) -> {
//calls viewModel.addBarcode(String barcode)
readBarcode(readBarcodeCallback);
});

}
}

最佳答案

您可以使用 PagedListAdapterHelper在您现有的适配器中,如下所示

class UserAdapter extends RecyclerView.Adapter<UserViewHolder> {
private final PagedListAdapterHelper<User> mHelper;
public UserAdapter(PagedListAdapterHelper.Builder<User> builder) {
mHelper = new PagedListAdapterHelper(this, DIFF_CALLBACK);
}
@Override
public int getItemCount() {
return mHelper.getItemCount();
}
public void setList(PagedList<User> pagedList) {
mHelper.setList(pagedList);
}
@Override
public void onBindViewHolder(UserViewHolder holder, int position) {
User user = mHelper.getItem(position);
if (user != null) {
holder.bindTo(user);
} else {
// Null defines a placeholder item - PagedListAdapterHelper will automatically
// invalidate this row when the actual object is loaded from the database
holder.clear();
}
}
public static final DiffCallback<User> DIFF_CALLBACK = new DiffCallback<User>() {
@Override
public boolean areItemsTheSame(
@NonNull User oldUser, @NonNull User newUser) {
// User properties may have changed if reloaded from the DB, but ID is fixed
return oldUser.getId() == newUser.getId();
}
@Override
public boolean areContentsTheSame(
@NonNull User oldUser, @NonNull User newUser) {
// NOTE: if you use equals, your object must properly override Object#equals()
// Incorrectly returning false here will result in too many animations.
return oldUser.equals(newUser);
}
}

用户 PageListAdapter

class UserAdapter extends PagedListAdapter<User, UserViewHolder> {
public UserAdapter() {
super(DIFF_CALLBACK);
}
@Override
public void onBindViewHolder(UserViewHolder holder, int position) {
User user = getItem(position);
if (user != null) {
holder.bindTo(user);
} else {
// Null defines a placeholder item - PagedListAdapter will automatically invalidate
// this row when the actual object is loaded from the database
holder.clear();
}
}
public static final DiffCallback<User> DIFF_CALLBACK = new DiffCallback<User>() {
@Override
public boolean areItemsTheSame(
@NonNull User oldUser, @NonNull User newUser) {
// User properties may have changed if reloaded from the DB, but ID is fixed
return oldUser.getId() == newUser.getId();
}
@Override
public boolean areContentsTheSame(
@NonNull User oldUser, @NonNull User newUser) {
// NOTE: if you use equals, your object must properly override Object#equals()
// Incorrectly returning false here will result in too many animations.
return oldUser.equals(newUser);
}
}

关于android - 实时数据列表 - 适配器不使用 DiffUtil 方法更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46771925/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com