我尝试创建一个简单的启动器,它在GridView
中显示应用列表,并且GridView没有平滑滚动。对resolveInfo.activityInfo.loadIcon(pm)
的调用似乎是造成滞后的因素。
活动
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Intent packIntent = new Intent(Intent.ACTION_MAIN,null);
packIntent.addCategory(Intent.CATEGORY_LAUNCHER);
final PackageManager pm = getPackageManager();
List<ResolveInfo> packList= pm.queryIntentActivities(packIntent, 0 );
GridView appGrid = (GridView) findViewById(R.id.appGrid);
GridAdapter gridAdapter = new GridAdapter(this, pm, packList);
appGrid.setAdapter(gridAdapter);
}
}
GridAdapter
public class GridAdapter extends BaseAdapter{
private PackageManager pm;
private List<ResolveInfo> packList;
private Context mContext;
public GridAdapter(Context mContext,PackageManager pm, List<ResolveInfo> packList) {
super();
this.mContext=mContext;
this.pm = pm;
this.packList = packList;
}
@Override
public int getCount() {
return packList.size();
}
@Override
public Object getItem(int position) {
return packList.get(position);
}
@Override
public long getItemId(int arg0) {
return 0;
}
static class ViewHolder{
TextView text;
ImageView image;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
LayoutInflater li = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView==null){
convertView = li.inflate(R.layout.drawer_item, null);
viewHolder = new ViewHolder();
viewHolder.text= (TextView)convertView.findViewById(R.id.icon_text);
viewHolder.image= (ImageView)convertView.findViewById(R.id.icon_image);
convertView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.text.setText(packList.get(position).loadLabel(pm));
viewHolder.image.setImageDrawable(packList.get(position).activityInfo.loadIcon(pm));
return convertView;
}
}
activity_main.xml中
<GridView
android:id="@+id/appGrid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="left"
android:columnWidth="80dp"
android:horizontalSpacing="10dp"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="10dp" />
</RelativeLayout>
和drawer_item.xml
<ImageView
android:id="@+id/icon_image"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="3dp"/>
<TextView
android:id="@+id/icon_text"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:maxLines="2"
android:gravity="center_horizontal"
/>
</LinearLayout>
我尝试创建一个具有
的自定义beanclass AppDetails{
Drawable icon;
String label;
}
并尝试填充这些
的列表for(int i = 0; i<packList.size();i++){
AppDetails temp = new AppDetails();
temp.icon=packList.get(i).activityInfo.loadIcon(pm);
temp.label=packList.get(i).loadLabel(pm).toString();
appDetails.add(temp);
}
并尝试为此构建适配器。如果我这样做,GridView滚动变得更平滑,但它会减慢Activity
的速度。尝试使用AyncTasks加载图标,但图标需要时间来通过AsyncTask加载..
是否有更好的方法来加载应用程序图标或缓存它?
答案 0 :(得分:0)
从适配器中的内部AsyncTask加载并设置图像,以便将图像加载到另一个线程上,这会消除很多延迟(无论如何它都适用于我)并为您的网格使用静态类ViewHolder。
答案 1 :(得分:0)
正如Pontus所说,在AsyncTask中加载图像会使你的加载时间更好,但是如果你想要“完美”平滑,你需要使用Cache,因为如果没有,你在滚动时不断重绘图标。
答案 2 :(得分:0)
你只需要使用异步任务。按照以下步骤。
Asynchtask
并在onCreate
。onPostExecute
方法从doInBackground
方法设置适配器。结果:您不会因此获得ANR(应用程序未工作响应),并且根据您的要求,活动也会变得更快。 这对我有用,我希望这对你们有所帮助。
如果您有任何疑问,请在此免费评论。
答案 3 :(得分:0)
将此类添加到适配器
private class IconLoaderTask extends AsyncTask<Void, Void, Drawable>
{
private mImageView;
private mPosition;
public IconLoaderTask(ImageView imageview, int position)
{
imageview.setTag(position);
}
public Drawable doInBackground()
{
return packList.get(position).activityInfo.loadIcon(pm)
}
public void onPostExcecute(Drawable drawable)
{
if(imageView.getTag() == mPosition){
imageView.setImageDrawable(drawable);
}
}
}
然后在你的getView方法中执行类似这样的操作
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Your code here
new IconLoaderTask(viewHolder.image, position).execute();
return convertView;
}
答案 4 :(得分:0)
目前你正试图加载&amp;在UI-Thread中创建Bitmap,并且因为UIThread被阻止了这个作业。因此,将此作业分配给非UI-Thread。也尝试回收&amp;尽可能重用位图。因为Bitmap的不当回收会频繁调用System.gc()
&amp;它也会在UI-Tread上调用,导致ScrollView
中的冻结影响(检查logcat,你会知道System.gc()
调用的频率。)
答案 5 :(得分:0)
我认为每个人都是正确的,activityInfo.loadIcon()应该使用AsyncTask从UI线程发生。从那里你可以考虑使用UrlImageViewHelper:
它内置了缓存,应该可以平滑滚动。您的用例有点偏离UrlImageViewHelper通常用于(通过URL下载的图像)。但它可以在其他场景中使用(例如,我用它来平滑从SD加载的图像)。
我多次使用UrlImageViewHelper。它工作得很好,通常很容易实现。
答案 6 :(得分:0)
您可以使用Picasso库缓存所有应用的图标来解决您的问题。在此链接中对此进行了解释 How to load image (icons) of apps faster in gridView?