java - 在 ListView 中从 apk 文件加载许多图标

标签 java android file listview android-asynctask

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

这是我的适配器类

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);

任何人都可以帮助我在不影响性能且不出现该错误的情况下顺利加载图标图像。

最佳答案

您可能需要使用 Loader类(class)。

The Loader API lets you load data from a content provider or other data source for display in an FragmentActivity or Fragment. If you don't understand why you need the Loader API to perform this seemingly trivial operation, then first consider some of the problems you might encounter without loaders:

  • If you fetch the data directly in the activity or fragment, your users will suffer from lack of responsiveness due to performing potentially slow queries from the UI thread.
  • If you fetch the data from another thread, perhaps with AsyncTask, then you're responsible for managing both the thread and the UI thread through various activity or fragment lifecycle events, such as onDestroy() and configurations changes.

Loaders solve these problems and includes other benefits. For example:

  • Loaders run on separate threads to prevent janky or unresponsive UI.
  • Loaders simplify thread management by providing callback methods when events occur.
  • Loaders persist and cache results across configuration changes to prevent duplicate queries.
  • Loaders can implement an observer to monitor for changes in the underlying data source. For example, CursorLoader automatically registers a ContentObserver to trigger a reload when data changes.

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

关于java - 在 ListView 中从 apk 文件加载许多图标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47597411/

相关文章:

java - 使用 Eclipse 的 Android 项目给出错误 : Cannot switch on a value of type String for source level below 1. 7

android - 如何在 Fragment 内的 WebView 中添加 "Go Back"函数?

c# - File.Replace 抛出 IOException

java - 32位java可以访问的最大文件大小是多少?

java - 将 MongoClient 与列表 ServerAddress 一起使用时出现 com.mongodb.MongoTimeoutException

java - OffsetDateTime 格式化和解析

android - SingleTask Activity ,但通过两个不同的应用程序打开

android - 应用程序死于 "Sending signal."但没有异常或其他信息

java - 查找文件的路径

java - 如果在父类(super class)中定义了方法,如何根据调用它的对象更改结果