【问题标题】:how to enhance & increase performance to recyclerView adapter如何增强和提高 recyclerView 适配器的性能
【发布时间】:2021-02-20 16:11:42
【问题描述】:

我有这个适配器,到目前为止工作得很好,但我在上面做了一些不好的练习代码,比如: - 在 OnBindView 中使用 onClickListener。

  • 使用 GC 清理我的内存,这也是一种不好的做法。
  • 我已经为适配器设置了一个列表和其他列表,以便在需要滚动时加载。那正确吗 ?或者我应该在设置适配器之前加载所有需要的列表。
  • 在更新适配器时,我通常会为非 notifyDataSetChanged 设置一个新适配器,因为它并不总是有效。
  • 要注意整个项目,我有一个用于设置 itemViewAdapter 的类别适配器。
  • itemViewAdapter 设置 colorItemsAdapter 如果项目有多个颜色。

我需要提高该代码的性能,因为我觉得滚动很多数据会变得迟钝。

这里是 itemViewAdapter 的代码:

public class ItemViewAdapter extends RecyclerView.Adapter<ItemViewAdapter.imagesHolder> {

List<iItem> Items;
Context context;
ExecutorService pool;
boolean isAdmin;

public ItemViewAdapter(List<iItem> items) {
    Items = items;
}

@NonNull
@Override
public ItemViewAdapter.imagesHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_main_items, parent, false);
    context = parent.getContext();
    isAdmin = ((Activity) context).getIntent().getBooleanExtra("isAdmin", false);

    return new imagesHolder(view);
}

@Override
public void onBindViewHolder(@NonNull imagesHolder holder, int position) {
    if (pool == null) {
        pool = Executors.newFixedThreadPool(10);
    }

    pool.execute(() -> {
        holder.colorItems = iItemDatabase.getDB(context).iItemDAO().getColorItems(Items.get(holder.getAdapterPosition()).getItemID());
        if (holder.colorItems != null) {
            if (holder.colorItems.size() != 0) {
                holder.tvItemName.setText(holder.colorItems.get(0).getItemName());
                if (holder.colorItems.get(0).getItemBPrice().equals("0")) {
                    holder.tvItemPriceB.setVisibility(View.INVISIBLE);
                } else {
                    holder.tvItemPriceB.setText(holder.colorItems.get(0).getItemBPrice() + " L.E");
                }
                holder.tvItemPriceA.setText(holder.colorItems.get(0).getItemAPrice() + " L.E");

                pool.execute(() -> {
                    holder.getImages = (List<iItemImages>) iItemDatabase.getDB(context).iItemImagesDAO().getImages(holder.colorItems.get(0).getItemID());
                    holder.semaphore.release();
                });
                holder.semaphore.acquireUninterruptibly();

                ((Activity) context).runOnUiThread(() -> {
                    if (holder.getImages.size() != 0) {
                        holder.tvImageSize.setText("1/" + holder.getImages.size());

                        holder.imageAdapter = new ImageAdapter(holder.getImages, isLongCLick -> {
                            if (!isLongCLick) {
                                onImageClick(holder.colorItems.get(holder.colorItemPosition).getItemID());
                            } else {
                                if (isAdmin) {
                                    onImageLongClick(holder.btnAddColor, holder.btnEdit, holder.btnDelete, holder.btnDeleteAll,
                                            holder.colorItems, holder.colorItemPosition, holder.alertDialog);
                                }
                            }
                        });
                        holder.rvItemImages1.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
                        holder.rvItemImages1.setAdapter(holder.imageAdapter);

                        if (holder.getImages.size() > 1) {
                            if (holder.handler == null) {
                                holder.handler = new Handler(Looper.getMainLooper());
                                holder.handler.postDelayed(holder.runnable, 4000);
                            }
                        }
                    }
                    holder.semaphore.release();
                });
                holder.semaphore.acquireUninterruptibly();

                if (holder.colorItems.size() >= 1) {
                    holder.imagesURL.clear();
                    for (iItem colorItem : holder.colorItems) {
                        holder.imagesURL.addAll(iItemDatabase.getDB(context).iItemImagesDAO().getFirstImageURL(colorItem.getItemID()));
                    }
                    holder.colorItemsAdapter = new ColorItemsAdapter(holder.colorItems, holder.imagesURL, position1 -> {
                        holder.colorItemPosition = position1;
                        holder.tvItemName.setText(holder.colorItems.get(position1).getItemName());
                        if (holder.colorItems.get(position1).getItemBPrice().equals("0")) {
                            holder.tvItemPriceB.setVisibility(View.INVISIBLE);
                        } else {
                            holder.tvItemPriceB.setText(holder.colorItems.get(position1).getItemBPrice() + " L.E");
                        }
                        holder.tvItemPriceA.setText(holder.colorItems.get(position1).getItemAPrice() + " L.E");

                        pool.execute(() -> {
                            holder.getImages = (List<iItemImages>) iItemDatabase.getDB(context).iItemImagesDAO().getImages(holder.colorItems.get(position1).getItemID());
                            holder.semaphore.release();
                        });
                        holder.semaphore.acquireUninterruptibly();

                        if (holder.getImages.size() != 0) {
                            holder.tvImageSize.setText("1/" + holder.getImages.size());

                            holder.imageAdapter = new ImageAdapter(holder.getImages, isLongCLick -> {
                                if (!isLongCLick) {
                                    onImageClick(holder.colorItems.get(holder.colorItemPosition).getItemID());
                                } else {
                                    if (isAdmin) {
                                        onImageLongClick(holder.btnAddColor, holder.btnEdit, holder.btnDelete, holder.btnDeleteAll,
                                                holder.colorItems, holder.colorItemPosition, holder.alertDialog);
                                    }
                                }
                            });
                            holder.rvItemImages1.setAdapter(holder.imageAdapter);

                            if (holder.getImages.size() > 1) {
                                if (holder.handler == null) {
                                    holder.handler = new Handler(Looper.getMainLooper());
                                    holder.handler.postDelayed(holder.runnable, 4000);
                                }
                            }
                        }
                        holder.colorItemsAdapter.notifyDataSetChanged();
                    });
                    ((Activity) context).runOnUiThread(() -> {
                        holder.rvColorItems.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
                        holder.rvColorItems.setAdapter(holder.colorItemsAdapter);
                        holder.semaphore.release();
                    });
                    holder.semaphore.acquireUninterruptibly();
                    Runtime.getRuntime().gc();
                }
            }
        }
        holder.rvItemImages1.addOnScrollListener(new RecyclerView.OnScrollListener() {

            @Override
            public void onScrollStateChanged(@NonNull @NotNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    holder.tvImageSize.setText((((LinearLayoutManager) Objects.requireNonNull(recyclerView.getLayoutManager())).findFirstVisibleItemPosition() + 1) + "/" + Objects.requireNonNull(recyclerView.getAdapter()).getItemCount());
                }
            }
        });
    });
    Runtime.getRuntime().gc();
}

void onImageClick(String ItemID) {
    Fragment fragment = new ItemsFragment2();
    Bundle bundle = new Bundle();
    bundle.putString("selectedItem", ItemID);
    fragment.setArguments(bundle);

    FragmentManager fragmentManager = ((AppCompatActivity) context).getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    Fragment fragment1 = fragmentManager.findFragmentByTag("ItemsFragment1");
    fragmentTransaction.hide(fragment1);
    fragmentTransaction.add(R.id.fl_MainItems, fragment, "ItemsFragment2").addToBackStack(null);
    fragmentTransaction.commit();
}

void onImageLongClick(Button btnAddColor, Button btnEdit, Button btnDelete, Button btnDeleteAll,
                      List<iItem> colorItems, int colorItemPosition, AlertDialog alertDialog) {
    Semaphore semaphore = new Semaphore(0);

    btnAddColor.setOnClickListener(v1 -> {
        Intent in = new Intent(context, AEDItem.class);
        in.putExtra("type", (byte) 3);
        in.putExtra("itemID", colorItems.get(0).getItemID());
        in.putExtra("colorID", colorItems.get(0).getColorID());
        context.startActivity(in);

        alertDialog.dismiss();
    });

    btnEdit.setOnClickListener(v1 -> {
        Intent in = new Intent(context, AEDItem.class);
        in.putExtra("type", (byte) 2);
        in.putExtra("itemID", colorItems.get(colorItemPosition).getItemID());
        in.putExtra("colorID", colorItems.get(colorItemPosition).getColorID());
        in.putExtra("itemName", colorItems.get(colorItemPosition).getItemName());
        context.startActivity(in);

        alertDialog.dismiss();
    });

    btnDelete.setOnClickListener(v12 -> {
        pool.execute(() -> {
            saveAdminUpdate(context,true);

            iItemDatabase.getDB(context).iItemDAO().DeleteItem(colorItems.get(colorItemPosition).getItemID());
            iItemDatabase.getDB(context).iItemImagesDAO().DeleteItemImage(colorItems.get(colorItemPosition).getItemID());

            FirebaseFirestore db = FirebaseFirestore.getInstance();
            db.collection("Items").document(colorItems.get(colorItemPosition).getItemID())
                    .delete()
                    .addOnSuccessListener(aVoid ->
                    {
                        FirebaseStorage storage = FirebaseStorage.getInstance();
                        StorageReference storageRef = storage.getReference();
                        StorageReference desertRef = storageRef.child("itemImages/" + colorItems.get(colorItemPosition).getItemID());

                        Task<ListResult> listResultTask = desertRef.listAll();
                        listResultTask.addOnSuccessListener(listResult -> {
                            for (StorageReference item : listResult.getItems()) {
                                item.delete().addOnSuccessListener(l -> {
                                });
                            }
                        });
                        semaphore.release();
                    });

            semaphore.acquireUninterruptibly();

            final int[] ExternalVersion = {retrieveVersion(context)};
            if (ExternalVersion[0] == 0) {
                // not found on shared, get it from server
                db.collection("Version").document("items")
                        .get()
                        .addOnCompleteListener(task -> {
                            pool.execute(() -> {
                                if (task.isSuccessful()) {
                                    if (task.getResult().get("v") != null) {
                                        // if found, add 1 to it
                                        ExternalVersion[0] = Integer.parseInt(task.getResult().get("v").toString());
                                        ExternalVersion[0]++;
                                    } else {
                                        // not found, create it
                                        ExternalVersion[0] = 1;
                                    }
                                }
                                semaphore.release(2);
                            });
                        });

                semaphore.acquireUninterruptibly();
            } else {
                // found on shared, add 1 to it
                ExternalVersion[0]++;
            }

            // update version on server and local
            Map<String, Integer> externalVersion = new HashMap<>();
            externalVersion.put("v", ExternalVersion[0]);
            db.collection("Version")
                    .document("items")
                    .set(externalVersion)
                    .addOnSuccessListener(documentReference1 -> {
                        pool.execute(() -> {
                            saveVersion(context, ExternalVersion[0]);
                            semaphore.release();
                        });
                    });
            semaphore.acquireUninterruptibly();

            ((Activity) context).runOnUiThread(() -> {
                View view = View.inflate(context, R.layout.rv_main_items, null);
                Snackbar.make(view, "Item deleted successfully", Snackbar.LENGTH_LONG).show();
                alertDialog.dismiss();

            });
        });
    });

    btnDeleteAll.setOnClickListener(v12 -> {
        pool.execute(() -> {
            saveAdminUpdate(context,true);
            List<String> itemIDs = new ArrayList<>();
            for (iItem colorItem : colorItems) {
                itemIDs.add(colorItem.getItemID());
            }
            iItemDatabase.getDB(context).iItemDAO().DeleteItems(itemIDs);
            iItemDatabase.getDB(context).iItemImagesDAO().DeleteItemImages(itemIDs);

            FirebaseFirestore db = FirebaseFirestore.getInstance();
            for (String itemID : itemIDs) {
                db.collection("Items").document(itemID)
                        .delete()
                        .addOnSuccessListener(aVoid ->
                        {
                            FirebaseStorage storage = FirebaseStorage.getInstance();
                            StorageReference storageRef = storage.getReference();
                            StorageReference desertRef = storageRef.child("itemImages/" + itemID);

                            Task<ListResult> listResultTask = desertRef.listAll();
                            listResultTask.addOnSuccessListener(listResult -> {
                                for (StorageReference item : listResult.getItems()) {
                                    item.delete().addOnSuccessListener(l -> {
                                    });
                                }
                            });
                            semaphore.release();
                        });
                semaphore.acquireUninterruptibly();
            }
            itemIDs.clear();

            final int[] ExternalVersion = {retrieveVersion(context)};
            if (ExternalVersion[0] == 0) {
                // not found on shared, get it from server
                db.collection("Version").document("items")
                        .get()
                        .addOnCompleteListener(task -> {
                            pool.execute(() -> {
                                if (task.isSuccessful()) {
                                    if (task.getResult().get("v") != null) {
                                        // if found, add 1 to it
                                        ExternalVersion[0] = Integer.parseInt(task.getResult().get("v").toString());
                                        ExternalVersion[0]++;
                                    } else {
                                        // not found, create it
                                        ExternalVersion[0] = 1;
                                    }
                                }
                                semaphore.release(2);
                            });
                        });

                semaphore.acquireUninterruptibly();
            } else {
                // found on shared, add 1 to it
                ExternalVersion[0]++;
            }

            // update version on server and local
            Map<String, Integer> externalVersion = new HashMap<>();
            externalVersion.put("v", ExternalVersion[0]);
            db.collection("Version")
                    .document("items")
                    .set(externalVersion)
                    .addOnSuccessListener(documentReference1 -> {
                        pool.execute(() -> {
                            saveVersion(context,ExternalVersion[0]);
                            semaphore.release();
                        });
                    });
            semaphore.acquireUninterruptibly();

            ((Activity) context).runOnUiThread(() -> {
                View view = View.inflate(context, R.layout.rv_main_items, null);
                Snackbar.make(view, "Items deleted successfully", Snackbar.LENGTH_LONG).show();
                alertDialog.dismiss();

            });
        });
    });
    alertDialog.show();

    Runtime.getRuntime().gc();
}

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

class imagesHolder extends RecyclerView.ViewHolder {
    TextView tvItemName, tvItemPriceA, tvItemPriceB, tvImageSize;
    RecyclerView rvItemImages1, rvColorItems;
    Handler handler;
    Runnable runnable;
    List<iItem> colorItems;
    List<iItemImages> getImages;
    Semaphore semaphore;
    ImageAdapter imageAdapter;
    ColorItemsAdapter colorItemsAdapter;
    List<String> imagesURL;
    int colorItemPosition = 0;
    AlertDialog.Builder alert;
    View mView;
    Button btnAddColor;
    Button btnEdit;
    Button btnDelete;
    Button btnDeleteAll;
    AlertDialog alertDialog;


    public imagesHolder(@NonNull View itemView) {
        super(itemView);
        rvItemImages1 = itemView.findViewById(R.id.rvItemImages1);
        rvColorItems = itemView.findViewById(R.id.rvColorItems);
        tvItemName = itemView.findViewById(R.id.tvItemName);
        tvItemPriceA = itemView.findViewById(R.id.tvItemPriceA);
        tvItemPriceB = itemView.findViewById(R.id.tvItemPriceB);
        tvImageSize = itemView.findViewById(R.id.tvImageSize);
        alert = new AlertDialog.Builder(itemView.getContext());
        mView = ((Activity) itemView.getContext()).getLayoutInflater().inflate(R.layout.custom_dialog, null);
        btnAddColor = mView.findViewById(R.id.btnAddColor);
        btnEdit = mView.findViewById(R.id.btnEdit);
        btnDelete = mView.findViewById(R.id.btnDelete);
        btnDeleteAll = mView.findViewById(R.id.btnDeleteAll);
        alert.setView(mView);
        alertDialog = alert.create();
        imagesURL = new ArrayList<>();
        semaphore = new Semaphore(0);
        runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    if ((((LinearLayoutManager) Objects.requireNonNull(rvItemImages1.getLayoutManager())).findFirstVisibleItemPosition() + 1) < Objects.requireNonNull(imageAdapter).getItemCount()) {
                        rvItemImages1.smoothScrollToPosition((((LinearLayoutManager) rvItemImages1.getLayoutManager()).findFirstVisibleItemPosition() + 1));
                    } else {
                        rvItemImages1.smoothScrollToPosition(0);
                    }
                    handler.postDelayed(this, 4000);
                } catch (Exception ignored) {
                }
            }
        };


        Runtime.getRuntime().gc();
    }
}

}

【问题讨论】:

    标签: android performance android-recyclerview android-room adapter


    【解决方案1】:

    您不应该运行数据库查询onBindViewHolder()。适配器应该已经知道数据。用data-binding library 替换每一个 视图持有者的UI 操作,最好一次性设置所有数据。首先,删除这个被严重滥用的行:Semaphore semaphore 并学习如何编写异步代码。此外,这通常不是必需的:Runtime.getRuntime().gc() 并且在查看代码的作用时不会提高性能。

    或者当isAdmin == truecreateViewHolder() 中时膨胀一个完全不同的XML。

    【讨论】:

    • 1) 所以我应该在适配器外部加载数据,然后用它输入适配器。 2)信号量仅用于等待特定任务(如数据库工作)完成然后让这些数据工作,如果我没有这样做,代码将通过池然后在最后执行它。 3) GC >>> 知道了 4) 我会考虑使用数据绑定,你还有什么要给我的?
    猜你喜欢
    • 1970-01-01
    • 2012-09-30
    • 2017-09-20
    • 1970-01-01
    • 2018-04-06
    • 1970-01-01
    • 1970-01-01
    • 2013-07-14
    • 1970-01-01
    相关资源
    最近更新 更多