【问题标题】:Problem rendering imageView delay in recyclerView在recyclerView中渲染imageView延迟的问题
【发布时间】:2019-11-15 03:22:47
【问题描述】:

您好,我的应用目前有一个大问题。我有一个 recyclerView,我用 back4app 的数据填充适配器。我已经和他们核实过了,我提出的查询没有任何延迟。无论如何,当我加载显示具有两行网格布局模式的回收器视图的片段时,问题如下。

这是在 onCreateViewHolder 中膨胀的 XML

当我在模拟器或手机中运行应用程序时,我在屏幕上看到了这种行为,几毫秒后图像正确显示,但这已经转化为糟糕的用户体验,使其行为缓慢。

这是我的片段...

 public class PropiedadesInmobiliariasFragment extends Fragment {

    private LinearLayoutManager layoutManager;
    RecyclerView recyclerInmobiliarias;
    ParseObject queryEmpresa;
    ParseObject empresa;
    String stringEmpresa;
    List<ParseObject> allItems;
    FragmentManager fm;
    ProgressBar pb;


    public PropiedadesInmobiliariasFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_propiedades_inmobiliarias, container, false);
        pb = view.findViewById(R.id.progress_bar_inmo);
        recyclerInmobiliarias=(RecyclerView)view.findViewById(R.id.recycler_inmobiliarias);

        //pb.setVisibility(View.VISIBLE);
        recyclerInmobiliarias.setVisibility(View.GONE);

        pb.setVisibility(View.VISIBLE);


        allItems=new ArrayList<>();

        queryEmpresa();
        layoutManager=new GridLayoutManager(getContext(),2);
        recyclerInmobiliarias.setLayoutManager(layoutManager);
        recyclerInmobiliarias.setHasFixedSize(true);


        recyclerInmobiliarias.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerInmobiliarias, new RecyclerTouchListener.ClickListener() {
            @Override
            public void onClick(View view, int position) {

                ParseObject item=allItems.get(position);

                String selectedObjectId= item.getObjectId();
                String nombrePro=item.getString("NombrePropiedad");
                ParseFile object1 = item.getParseFile("imagenPrincipal");
                ParseFile imagen1 = item.getParseFile("imagen1");
                ParseFile imagen2 = item.getParseFile("imagen2");
                ParseFile imagen3 = item.getParseFile("imagen3");
                ParseFile imagen4 = item.getParseFile("imagen4");
                ParseFile imagen5 = item.getParseFile("imagen5");
                ParseFile imagen6 = item.getParseFile("imagen6");
                ParseFile imagen7 = item.getParseFile("imagen7");
                ParseFile imagen8 = item.getParseFile("imagen8");

                String precio=item.getString("Precio");
                String numHabita=item.getString("numeroDeHabitaciones");
                String metrosCuadrados=item.getString("metrosCuadrados");
                String numeroBanos=item.getString("numeroBanos");
                String descrip=item.getString("descripcionAdicionalPropiedad");
                String admin=item.getString("valorAdministracion");
                String numPar=item.getString("Parqueaderos");

                Bundle bundle=new Bundle();
                bundle.putString("objectId",selectedObjectId);
                bundle.putString("Nombre",nombrePro);
                bundle.putString("primeraFoto", object1.getUrl());
                bundle.putString("precio",precio);
                bundle.putString("numHab",numHabita);
                bundle.putString("metrosCua",metrosCuadrados);
                bundle.putString("numBanos",numeroBanos);
                bundle.putString("des",descrip);
                bundle.putString("admin",admin);
                bundle.putString("parq",numPar);

                Intent intent = new Intent(getActivity(), DetalleInmobiliaria.class);
                intent.putExtra("objectId", selectedObjectId);
                intent.putExtra("Nombre", nombrePro);
                intent.putExtra("primeraFoto", object1.getUrl());
                intent.putExtra("precio", precio);
                intent.putExtra("numHab", numHabita);
                intent.putExtra("metrosCua", metrosCuadrados);
                intent.putExtra("numBanos", numeroBanos);
                intent.putExtra("des", descrip);
                intent.putExtra("admin", admin);
                intent.putExtra("parq", numPar);
                startActivity(intent);
            }
            @Override
            public void onLongClick(View view, int position) {

            }
        }));

        return view;


    }

    private void queryEmpresa(){
        /**Ojo no es que no este sirviendo el metodo sino que el tipo de empresa asignado al usuario
         * no concuerda para que llene el recycler*/
        ParseQuery<ParseUser> query = ParseUser.getQuery();
        query.whereEqualTo("objectId",ParseUser.getCurrentUser().getObjectId());
        query.include("Empresa");
        query.getInBackground(ParseUser.getCurrentUser().getObjectId(), new GetCallback<ParseUser>() {
            public void done(ParseUser object, ParseException e) {
                if (e == null) {
                    // object will be your user and you should be able to retrieve Empresa like this
                    empresa = object.getParseObject("Empresa");
                    stringEmpresa=empresa.getObjectId();
                    queryPropInmo();
                } else {
                    // something went wrong. It would be good to log.
                }
            }
        });

    }

    private void queryPropInmo(){
        ParseQuery<ParseObject> query1 = ParseQuery.getQuery("PropiedadesInmobiliarias");
        queryEmpresa=ParseObject.createWithoutData("Empresa",stringEmpresa);
        query1.whereEqualTo("Empresa",queryEmpresa);
        query1.include("Empresa");
        query1.include("Imagenes");

       query1.findInBackground(new FindCallback<ParseObject>() {
           @Override
           public void done(List<ParseObject> objects, ParseException e) {


               if(objects!=null) {

                   for (ParseObject obj : objects
                   ) {
                       allItems.add(obj);

                   }
               }
               InmobiliariaAdapter adapter = new InmobiliariaAdapter(getActivity(),allItems);
               recyclerInmobiliarias.setAdapter(adapter);
               adapter.notifyDataSetChanged();
           }
       });

        pb.setVisibility(View.GONE);
        recyclerInmobiliarias.setVisibility(View.VISIBLE);
    }
}

这是我的适配器...

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


    Context context;
    List<ParseObject> inmobiliList;

    public InmobiliariaAdapter(Context context, List<ParseObject> inmobiliList) {
        this.context = context;
        this.inmobiliList = inmobiliList;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {

        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_carros, viewGroup, false);


        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder viewHolder, final int position) {


        ParseObject item = inmobiliList.get(position);

        viewHolder.imagen.post(new Runnable() {
            @Override
            public void run() {
                loadBitmap(item,viewHolder);
            }
        });

        viewHolder.nombrePropInmobi.setText(item.getString("NombrePropiedad"));



    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {
        ImageView imagen;
        TextView nombrePropInmobi;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            imagen = (ImageView) itemView.findViewById(R.id.imgCarro);
            nombrePropInmobi = (TextView) itemView.findViewById(R.id.txttitulo);
        }

    }

    private void loadBitmap(ParseObject item, ViewHolder viewHolder){
        ParseFile parseFile = item.getParseFile("imagenPrincipal");
        if (parseFile != null) {
            parseFile.getDataInBackground(new GetDataCallback() {
                @Override
                public void done(byte[] data, ParseException e) {
                    if (e == null) {
                        Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
                        if (bmp != null) {
                            viewHolder.imagen.setImageBitmap(bmp);
                        }
                    }
                }
            });
        }



    }
}

我没有使用模型类我只是从服务器获取我需要的东西我什至已经实现了各种尝试解决这个问题的东西,我尝试了进度条甚至处理程序我也想过实现异步任务但是查询.findInBackground 及其 done 方法已经处理异步调用,现在我担心 Runnable 的实现可能会转变为内存泄漏。这里真正的问题是应用程序首先显示 XML 中的元素,这些元素在回收器视图中的每个位置的适配器中膨胀。我想要完成的是只有当后端的图像真正完成加载时才会显示回收器视图我真的不知道是什么原因造成的。目前列表中有 5 个项目,我不想用 3000 个项目来描绘它,:(,请帮助!!!!。

【问题讨论】:

  • 你可以显示一个加载器,直到你所有的背景图像都被获取,我真的会在这里使用 RX 和 Observables。此外,您可能想要使用某种分页。观看此视频:youtube.com/watch?v=Ej8iHKMVCmQ,虽然您不需要平面地图,但您会很好地了解如何使用 RX
  • 嘿,skynet 有什么办法可以在不从 jetpack 实现的情况下实现这一点,我刚开始学习 MVVM 将需要永远。:(
  • 我想你是在主线程上解码文件,为什么不把它卸载到后台线程呢?检查:medium.com/@imohchard/…
  • 嗨,skynet 我按照中篇文章中的建议实施了 Glide,但仍然存在问题

标签: android performance android-recyclerview


【解决方案1】:

您可以使用 GlidePicasso 等库来完成这项工作。这些是轻量级、良好的库,具有缓存能力,并自动将图像的优化版本加载到您的 ImageView 中。它自动管理存储和删除缓存。同样,直到那时,您的图像还没有被下载,他们可以选择在下载图像时显示 placeholder。它还可以用于预览本地图像并根据您的 ImageView 进行优化。

类似这样的:

Glide.with(context)
.load("https://raw.githubusercontent.com/bumptech/glide/master/static/glide_logo.png")
.placeholder(R.drawable.circularProgressDrawable)
.into(IMAGE_VIEW)

【讨论】:

    【解决方案2】:

    使用 Glide builder 来构建异步加载。

    科特林

       Glide.with(context)
                        .load(url)
                        .error(R.drawable.error)
                        .placeholder(R.drawable.placeholder)
                        .priority(Priority.HIGH)
                        .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
                        .override(60, 60)
                        .transition(DrawableTransitionOptions.withCrossFade(AppConstants.CROSS_FADE_DIRATION))
                        .transform(//based on requirements)
                        .into(target) // Async load the image
    
       private val target = object : CustomTarget<Drawable>() {
            override fun onLoadCleared(placeholder: Drawable?) {
    
            }
    
            override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
               // OnImage ready set the image with the drawable
            }
    
            override fun onLoadFailed(errorDrawable: Drawable?) {
                // OnFail set the error drawable to the view
    
            }
    
        }
    

    Java 代码

    Glide.with(getContext())
                        .load(getUrl()// load content)
                        .error(R.drawable.error)
                        .placeholder(R.drawable.placeholder)
                        .priority(Priority.HIGH)
                        .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
                        .override(60, 60)
                        .transition(DrawableTransitionOptions.withCrossFade(AppConstants.CROSS_FADE_DIRATION))
                        .transform(//based on requirements)
                        .into(target) // Async load the image
    
       private CustomTarget<Drawable> target = new CustomTarget<Drawable>() {
            @Override
            void onLoadCleared(@Nullable Drawable placeholder) {
    
            }
    
            @Override 
            void onResourceReady(Drawable resource,@Nullable Transition<in Drawable> transistion) {
               // OnImage ready set the image with the drawable
            }
    
            @Override
            void onLoadFailed(@Nullable Drawable errorDrawable ) {
                // OnFail set the error drawable to the view
    
            }
    
        }
    

    【讨论】:

    • 你好 SURYA N 你能帮我把代码用java吗?我还不了解 Kotlin!很好的答案非常感谢!
    • 您好,我没有将答案标记为正确答案,因为无论如何这都没有解决问题,非常感谢您的回答和时间。
    • 然后将 PagedAdapter 和 Pagedlist 与 liveData 一起使用
    猜你喜欢
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    相关资源
    最近更新 更多