当列表视图获得太多项目时,ViewPager 滞后



我正在使用带有四个选项卡(片段)的viewpager(SmartTabLayout)。在所有四个片段中,我都使用自定义列表视图。这些列表视图按项目从 SD 卡加载图像。为此,我使用Nostra的通用图像加载器。

到目前为止一切正常。但是,当我将上述列表视图之一中的项目数从 10 个增加到大约 50 个项目时,视图页不再流畅地滑动。

我对图片使用内存和光盘缓存。以下是我对图像加载器的配置:

File cacheDir = StorageUtils.getOwnCacheDirectory(context, 
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + Constants.DIRECTORY_TEAM_CHANNEL);//for caching
    ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context);
    config.diskCacheFileNameGenerator(new HashCodeFileNameGenerator());
    config.diskCacheSize(50 * 1024 * 1024); // 50 MiB
    config.diskCache(new UnlimitedDiskCache(cacheDir)); // You can pass your own disc cache implementation
    config.memoryCacheSize(41943040);
    config.threadPoolSize(10);
    ImageLoader.getInstance().init(config.build());

我使用以下选项参数:

mImgDisplayOptions = new DisplayImageOptions.Builder()
            .showImageOnLoading(R.drawable.default_user)
            .showImageForEmptyUri(R.drawable.default_user)
            .showImageOnFail(R.drawable.default_user)
            .cacheInMemory(true)
            .cacheOnDisc(true)
            .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
            .build();

下面是完整的列表视图适配器:

public class CustomContactListAdapter extends BaseAdapter
{
private static final int TYP_REGISTERED = 0;
private static final int TYP_UNREGISTERED = 1;
private static final int VIEW_TYPE_COUNT = 2;
private Activity activity;
private List<User> userItems;
private DisplayImageOptions mOptions;
private DBHandler dbHandler;
private DisplayImageOptions mImgDisplayOptions;
static ImageLoader imageLoader = ImageLoader.getInstance();
public CustomContactListAdapter(Activity activity, List<User> userItems)
{
    this.activity = activity;
    this.userItems = userItems;
    dbHandler = DBHandler.getInstance(activity.getApplicationContext());

    mImgDisplayOptions = new DisplayImageOptions.Builder()
            .showImageOnLoading(R.drawable.default_user)
            .showImageForEmptyUri(R.drawable.default_user)
            .showImageOnFail(R.drawable.default_user)
            .cacheInMemory(true)
            .cacheOnDisc(true)
            .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
            .build();
}
@Override
public int getCount()
{
    return userItems.size();
}
@Override
public Object getItem(int position)
{
    return userItems.get(position);
}
@Override
public long getItemId(int position)
{
    return position;
}
@Override
public int getItemViewType(int position) 
{
    return (userItems.get(position).getToken() != null) ? TYP_REGISTERED : TYP_UNREGISTERED;
}
@Override
public int getViewTypeCount()
{
    return VIEW_TYPE_COUNT;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    ViewHolder viewholder=null;
    int type = getItemViewType(position);    
    if (convertView == null)
    {    
        viewholder = new ViewHolder();
        LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        switch(type)
        {
            case TYP_REGISTERED:
                convertView = inflater.inflate(R.layout.contact_list_row, parent, false);
                viewholder.thumbNail = (ImageView ) convertView.findViewById(R.id.thumbnail_reg);
                viewholder.name = (TextView) convertView.findViewById(R.id.name_reg);
                viewholder.lastComment = (TextView) convertView.findViewById(R.id.lastComment_reg);
                viewholder.regState = (TextView) convertView.findViewById(R.id.regState_reg);
                viewholder.thumbNail.setMaxHeight(60);
                viewholder.thumbNail.setMaxWidth(60);
                break;
            case TYP_UNREGISTERED:
                convertView = inflater.inflate(R.layout.contact_list_not_registered_row, parent, false);
                viewholder.thumbNail = (ImageView) convertView.findViewById(R.id.thumbnail_not_reg);
                viewholder.name = (TextView) convertView.findViewById(R.id.name_not_reg);
                viewholder.phonenumber = (TextView) convertView.findViewById(R.id.phonenumber_not_reg);
                viewholder.regState = (TextView) convertView.findViewById(R.id.regState_not_reg);
                viewholder.thumbNail.setMaxHeight(60);
                viewholder.thumbNail.setMaxWidth(60);
                break;
        }
        convertView.setTag(viewholder);            
    }
    else
    {
        viewholder = (ViewHolder) convertView.getTag();
    }
    // getting user data for the row
    User user = userItems.get(position);
    String userName = "";
    switch(type)
    {
        case TYP_REGISTERED:
        {
            //thumbnail
            if (user.getThumbnail() != null)
            {
                if(user.getThumbnail() != null)
                {
                    imageLoader.displayImage(Constants.ABS_PATH_USER_THUMBNAIL + user.getThumbnail() + ".jpg", viewholder.thumbNail, mImgDisplayOptions);
                }
                else
                {
                    viewholder.thumbNail.setImageResource(R.drawable.default_user);
                }
            }
            else
            {
                viewholder.thumbNail.setImageResource(R.drawable.default_user);
            }
            //firstname
            if (user.getFirstname() != null) {
                userName += user.getFirstname() + " ";
            }
            //lastname
            if (user.getLastname() != null) {
                userName += user.getLastname();
            }
            viewholder.name.setText(userName);

            Chat chat = dbHandler.getChatByUser(user);
            if (chat != null) {
                Comment lastComment = dbHandler.getLastCommentFromUser(chat, user);
                if (lastComment != null) {
                    viewholder.lastComment.setText((lastComment.getContent().length() > 25)
                            ? lastComment.getContent().substring(0, 25) + "..." : lastComment.getContent());
                } else {
                    viewholder.lastComment.setText("");
                }
            } else {
                viewholder.lastComment.setText("");
            }

            // registration state (registered)
            viewholder.regState.setText(String.valueOf("mobil"));
            break;
        }
        case TYP_UNREGISTERED:
        {
            if (user.getThumbnail() != null)
            {
                if(user.getThumbnail() != null)
                {
                    imageLoader.displayImage(Constants.ABS_PATH_USER_THUMBNAIL + user.getThumbnail() + ".jpg", viewholder.thumbNail, mImgDisplayOptions);
                }
                else
                {
                    viewholder.thumbNail.setImageResource(R.drawable.default_user);
                }
            }
            else
            {
                viewholder.thumbNail.setImageResource(R.drawable.default_user);
            }
            if (user.getFirstname() != null) {
                userName += user.getFirstname() + " ";
            }
            if (user.getLastname() != null) {
                userName += user.getLastname();
            }
            viewholder.name.setText(userName);

            // phonenumber
            viewholder.phonenumber.setText(user.getPhonenumber());
            // registration state (unregistered, send invitation)
            viewholder.regState.setText(String.valueOf("Einladen"));
            break;
        }
    }
    return convertView;
}
private static class ViewHolder
{
    ImageView thumbNail;
    TextView name;
    TextView phonenumber;
    TextView lastComment;
    TextView regState; 
}
}

ListViews 在滚动离开屏幕时不会回收其视图。具有大量片段,每个片段在 ListView 中呈现图像的成本可能相当高。

如果您想

避免滞后,请查看回收器视图。它们有很好的文档记录,易于实现,堆效率更高。

更新:
我注意到您在滚动时正在加载图像(我认为这不是问题,因为它应该异步加载)。

根据文档,您可以在通过PauseOnScrollListener滚动列表视图时暂停加载。
要避免列表(网格等)滚动滞后,您可以使用 PauseOnScrollListener:

boolean pauseOnScroll = false; // or true
boolean pauseOnFling = true; // or false
PauseOnScrollListener listener = new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling);
listView.setOnScrollListener(listener);

直接从有用信息 UIL 文档中
获取。希望这能解决问题:)

更新
对于那些想要在RecyclerView上使用PauseOnScrollListener的人,以下是nostra13的实现:https://gist.github.com/nostra13/806d01ebd604f3adf241

查看页的问题在于它们在当前视图之前夸大视图。如果您正在膨胀大量资源,例如您现在正在做的事情,这可能会导致问题。我建议只夸大列表视图而不是所有信息。在活动中使用 onPageSelected 方法调用方法以开始加载信息。这样,仅加载活动片段。如果您仍然不确定我的意思,请告诉我!

最新更新