Issue
I am trying to load the icon from many apk files to a listview.
This is my adapter class
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");
}
}
}
But the main problem is as soon as I set the adapter it takes some time for all the Icon Images to get loaded and till then the phone gets hanged.
I have tried using a AsyncTask but This is the error I get
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]
I know that this error is occurring because I am queuing many AsyncTask at the same time.
My app has one/two more AsyncTask(For different purpose which cannot be avoided) running simultaneously so It is not possible for me to wait for them to get over and then to load the icons.
So I have to call the AsyncTask to get executed using the below Code.
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,path_to_icon);
Can Anyone please help me to load the Icon Images smoothly without effecting the performance and without getting that error.
Solution
You'll probably need to use a 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.
And here's a blog post that you may also find useful: http://www.technotalkative.com/android-asynchronous-image-loading-in-listview/
Answered By - Glaucus
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.