从ListView中的apk文件加载许多图标

时间:2017-12-01 16:21:52

标签: java android file listview android-asynctask

我正在尝试将图标从许多apk文件加载到列表视图。

这是我的适配器类

public class Apk_Adapter extends BaseAdapter {
    private ArrayList<File> apk;
    private my_activity activity;
    public static ArrayList<Integer> selection=new ArrayList<>();
    public Adapter (my_activity  activity, ArrayList<File> list) {
        super();
        this.apk = list;
        this.activity = activity;
        selection.clear();
    }

    @Override
    public int getCount() {
        return apk.size();
    }

    @Override
    public String getItem(int position) {
        return String.valueOf(apk.get(position));
    }

    @Override
    public long getItemId(int position) {

        return 0;
    }

    public class ViewHolder {
        public ImageView apk_img;
        public TextView name;
        public TextView size;
        public CheckBox tick;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {


        final ViewHolder view;


        LayoutInflater inflator = activity.getLayoutInflater();

        if (convertView == null) {


            view = new ViewHolder();

            convertView = inflator.inflate(R.layout.apk_adapter, null);

            view.apk_img = (ImageView) convertView.findViewById(R.id.img);
            view.size = (TextView) convertView.findViewById(R.id.size);
            view.name= (TextView) convertView.findViewById(R.id.name);
            view.tick= (CheckBox) convertView.findViewById(R.id.checkBox);

            convertView.setTag(view);
        } else {
            view = (ViewHolder) convertView.getTag();
        }
        view.tick.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
               //DO SOMETHING
            }
        });

        view.name.setText(apk.get(position).getName());
        view.size.setText(get_size(apk.get(position).length()));
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        get_apk_image(apk.get(position),activity.getApplication()).compress(Bitmap.CompressFormat.PNG, 100, stream);
        Glide.with(activity.getApplicationContext())
                .load(stream.toByteArray())
                .placeholder(R.drawable.apk)
                .centerCrop()
                .diskCacheStrategy(DiskCacheStrategy.RESULT)
                .thumbnail(0.5f)
                .into(view.apk_img);
        if (selection.contains(new Integer(position))) {
            view.tick.setChecked(true);
        } else {

            view.tick.setChecked(false);
        }
           return convertView;
    }


    public Bitmap get_apk_image(File file,Context context)
    {
        String filePath = file.getPath();
        PackageInfo packageInfo = context.getPackageManager().getPackageArchiveInfo(filePath, PackageManager.GET_ACTIVITIES);
        if(packageInfo != null) {
            ApplicationInfo appInfo = packageInfo.applicationInfo;
            if (Build.VERSION.SDK_INT >= 8) {
                appInfo.sourceDir = filePath;
                appInfo.publicSourceDir = filePath;
            }
          final  Drawable icon = appInfo.loadIcon(context.getPackageManager());
            return ((BitmapDrawable) icon).getBitmap();

        }
        return null;
    }
    public double round(double value, int places) {
        if (places < 0) throw new IllegalArgumentException();
        BigDecimal bd = new BigDecimal(value);
        bd = bd.setScale(places, RoundingMode.HALF_UP);
        return bd.doubleValue();
    }


    public String get_size(double bytes)
    {
        if(bytes>(1024*1024*1024))
        {
            return String.valueOf(round((bytes/(1024*1024*1024)),2)+"GB");
        }
        else  if(bytes>(1024*1024))
        {
            return String.valueOf(round((bytes/(1024*1024)),2)+"MB");
        }
        else
        {
            return String.valueOf(round((bytes/(1024)),2)+"KB");
        }
    }

}

但主要的问题是,一旦我设置了适配器,所有图标图像都需要一段时间才能加载,直到那时手机被挂起。

我尝试过使用AsyncTask但是 这是我得到的错误

Fatal Exception: java.util.concurrent.RejectedExecutionException
Task android.os.AsyncTask$3@16ffd1b rejected from java.util.concurrent.ThreadPoolExecutor@9af2eb8[Running, pool size = 9, active threads = 9, queued tasks = 128, completed tasks = 246]

我知道这个错误正在发生,因为我正在同时排队许多AsyncTask。

我的应用程序有一两个AsyncTask(出于不同的目的,无法避免)同时运行,因此我无法等待它们过来然后加载图标。

所以我必须使用下面的代码调用AsyncTask来执行。

task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,path_to_icon);

任何人都可以帮我顺利加载图标图像,而不会影响性能,也不会出现错误。

1 个答案:

答案 0 :(得分:1)

您可能需要使用Loader课程。

  

Loader API允许您从内容提供商或其他人加载数据   用于在FragmentActivity或Fragment中显示的数据源。如果你   不明白为什么你需要Loader API来表现这一点   琐碎的操作,然后首先考虑一些你可能遇到的问题   没有装载者的遭遇:

     
      
  • 如果直接在活动或片段中获取数据,您的用户将因执行而缺乏响应能力   来自UI线程的潜在慢查询。
  •   
  • 如果您从另一个线程获取数据,也许使用AsyncTask,那么您负责管理线程和UI线程   通过各种活动或片段生命周期事件,例如   onDestroy()和配置更改。
  •   
     

装载机解决了这些问题并包含其他好处。例如:

     
      
  • 加载程序在不同的线程上运行,以防止janky或无响应的UI。
  •   
  • 加载程序通过在事件发生时提供回调方法来简化线程管理。
  •   
  • 加载程序会在配置更改中保持并缓存结果,以防止重复查询。
  •   
  • 加载程序可以实现观察者来监视基础数据源的更改。例如,CursorLoader自动   注册ContentObserver以在数据更改时触发重新加载。
  •   

这是一篇你可能也觉得有用的博文:http://www.technotalkative.com/android-asynchronous-image-loading-in-listview/