启动器应用程序:改善性能和滚动体验

时间:2014-02-25 06:52:51

标签: android performance gridview android-launcher

我尝试创建一个简单的启动器,它在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>

我尝试创建一个具有

的自定义bean
class 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加载..

是否有更好的方法来加载应用程序图标或缓存它?

7 个答案:

答案 0 :(得分:0)

从适配器中的内部AsyncTask加载并设置图像,以便将图像加载到另一个线程上,这会消除很多延迟(无论如何它都适用于我)并为您的网格使用静态类ViewHolder。

答案 1 :(得分:0)

正如Pontus所说,在AsyncTask中加载图像会使你的加载时间更好,但是如果你想要“完美”平滑,你需要使用Cache,因为如果没有,你在滚动时不断重绘图标。

答案 2 :(得分:0)

你只需要使用异步任务。按照以下步骤。

  1. 创建Asynchtask并在onCreate
  2. 中简单地初始化它
  3. 使用onPostExecute方法从doInBackground方法设置适配器。
  4. 结果:您不会因此获得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

它内置了缓存,应该可以平滑滚动。您的用例有点偏离UrlImageViewHelper通常用于(通过URL下载的图像)。但它可以在其他场景中使用(例如,我用它来平滑从SD加载的图像)。

我多次使用UrlImageViewHelper。它工作得很好,通常很容易实现。

答案 6 :(得分:0)

您可以使用Picasso库缓存所有应用的图标来解决您的问题。在此链接中对此进行了解释 How to load image (icons) of apps faster in gridView?