我正在尝试将图标从许多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);
任何人都可以帮我顺利加载图标图像,而不会影响性能,也不会出现错误。
答案 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/