在Spinner中加载大量数据时,应用程序冻结

问题描述

我正在微调器中加载国家/地区列表,它们大约有225个项目,每个项目都有一张图片

我正在将其加载为片段。问题是当我到达此片段时,应用程序冻结了2-3秒。

我也尝试将其加载到线程中,但没有帮助。

以下是我的代码

片段中的旋转码

var spinnerAdapter : CountriesAdapter?= null
            val runnable= Runnable {
                spinnerAdapter= CountriesAdapter(activity?.applicationContext,R.layout.country_component,CountriesModel.getCountryDataList())

                spinnerNationality?.setAdapter(spinnerAdapter)
            }

        val thread = Thread(runnable)
        thread.start()

自定义适配器

public class MyAdapter extends ArrayAdapter {

    Context context;
    List<CountriesDTO> objects;
    int textViewResourceId;

    public MyAdapter(Context context,int textViewResourceId,List<CountriesDTO> objects) {
        super(context,textViewResourceId,objects);

        this.objects= objects;
        this.context= context;
        this.textViewResourceId= textViewResourceId;
    }

    public View getCustomView(int position,View convertView,ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View row = inflater.inflate(textViewResourceId,parent,false);
        TextView label = (TextView) row.findViewById(R.id.tvCountry);
        ImageView ivFlag =  row.findViewById(R.id.ivCountryFlag);

        label.setText(objects.get(position).getCountryName());

        Glide.with(context)
                .load(objects.get(position).getCompleteFlagURL())
                .into(ivFlag);

        return row;
    }

    @Override
    public View getDropDownView(int position,ViewGroup parent) {
        return getCustomView(position,convertView,parent);
    }

    @Override
    public View getView(int position,parent);
    }
}

解决方法

考虑到不同的UX设计,没有构建Spinner来显示225个项目。您想将RecyclerView用于这么多项目。

最简单的选择是导航到用户选择国家的单独Fragment。您也可以使用DialogFragment。或者,您可以显示带有自定义视图的PopupWindow

编辑:我看到您没有回收微调器视图,这会使您的适配器膨胀225个视图。但是,从UX的角度来看,您仍可能要考虑使用单独的片段一次显示更多项目。

您要像这样回收适配器视图:

public View getCustomView(int position,View convertView,ViewGroup parent) {

    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View row;
    if (convertView == null) {
        // only inflate a new view when we don't recycle one
        row = inflater.inflate(textViewResourceId,parent,false);
    } else {
        // recycle convertView
        row = convertView
    }
    
    // these findViewById() calls are also slowing you down
    TextView label = (TextView) row.findViewById(R.id.tvCountry);
    ImageView ivFlag =  row.findViewById(R.id.ivCountryFlag);

    label.setText(objects.get(position).getCountryName());

    Glide.with(context)
            .load(objects.get(position).getCompleteFlagURL())
            .into(ivFlag);

    return row;
}