即使使用ViewHolder,Android ListView也会延迟每个滚动

时间:2015-11-22 19:49:47

标签: android performance listview parse-platform android-adapter

我想提供一些背景信息:我目前参与帮助开发的应用是一家公司已经为IOS和Android开发的应用,但Android开发者没有提供预期的结果(主要是性能明智)所以领导给了我代码,看看我是否可以解决它。鉴于代码我试图改进它,现在,该应用程序是一个图片共享应用程序有点像Instagram,它使用和无休止的滚动列表,应用程序的问题是每次我滚动一点点,应用程序滞后或冻结一秒钟,然后加载一个新行。

列表视图随时只能显示一行。

我尝试了什么?:

适配器没有使用ViewHolder模式,所以我尝试实现它。

程序员在getView方法上定义了很多点击监听器,所以我删除了它们。

仍然,每次我滚动(一个新行出现,因为任何时候只有一个可见行)它会滞后。这里有任何其他明显的问题可能是原因吗?

另一方面,在这个视图中有很多透支,所以它可能会影响ListView的性能吗?如果是这样,请告诉我,我将发布XML部分。

这是我改编的代码:

public class SomeFragment extends Fragment  implements SwipeRefreshLayout.OnRefreshListener {

// declaration and constructors.....

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {

  //initialization......
  //setting variables.......
  //getting views.....
    listview = (ListView)rootView.findViewById(R.id.listview);

    listview.setOnScrollListener(new AbsListView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            int threshold = 1;
            int count = listview.getCount();

            if (scrollState == SCROLL_STATE_IDLE) {
                if (listview.getLastVisiblePosition() >= count - threshold) {
                    int position = listview.getLastVisiblePosition();
                    if (!loading) {
                        loading = true;
                        listview.addFooterView(footerView, null, false);
                        currentVal = position + 1;
                        LoadMoreStuffAsyncTask loadMoreStuffAsyncTask = new LoadMoreStuffAsyncTask();
                        loadMoreStuffAsyncTask.execute();
                    }

                }
            }
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            int topRowVerticalPosition = (listview == null || listview.getChildCount() == 0) ? 0 : listview.getChildAt(0).getTop();
            swipeRefreshLayout.setEnabled(firstVisibleItem == 0 && topRowVerticalPosition >= 0);
        }
    });
    LoadStuffAsyncTask loadStuffAsyncTask=new LoadStuffAsyncTask();
    loadStuffAsyncTask.execute();

}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    rootView = inflater.inflate(R.layout.activity, container, false);
    swipeRefreshLayout = (SwipeRefreshLayout)rootView.findViewById(R.id.swipe);
    swipeRefreshLayout.setOnRefreshListener(SomeFragment.this);

    return  rootView;
}


private void  LoadStuff () {
    list=null;
    ParseQuery<ParseObject> query = null;
    query = ParseQuery.getQuery("Objects");
    query.orderByDescending("createdAt");
    query.include("User");
    query.setLimit(20);

    try {
        list = query.find();

    } catch (ParseException e) {
        e.printStackTrace();
    }
}

private void LoadMoreStuff () {

    List<ParseObject> moreList=null;
    ParseQuery<ParseObject> query = null;
    query = ParseQuery.getQuery("Objects");
    query.orderByDescending("createdAt");
    query.include("User");
    query.setLimit(20);
    query.setSkip(currentVal);

    try {
        moreList = query.find();
        if(moreList!=null|| moreList.size()!=0){
            for(int i =0;i<moreList.size();i++){
                list.add(moreList.get(i));
            }
        }else{
            loading=false;
        }

    } catch (ParseException e) {
        e.printStackTrace();
        loading=false;
    }
}

@Override
public void onRefresh() {
    swipeRefreshLayout.setRefreshing(true);
    listAdapter.notifyDataSetChanged();
    LoadStuffAsyncTask loadStuffAsyncTask=new LoadStuffAsyncTask();
    loadStuffAsyncTask.execute();
}

class LoadMoreStuffAsyncTask extends  AsyncTask<Void, Void, Void>{
    private ProgressDialog pDialog;

    @Override
    protected Void doInBackground(Void... params) {
        LoadMoreStuff();
        return null;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        listAdapter.updateList(list);
        listview.setAdapter(listAdapter);
        loading=false;
        listview.removeFooterView(footerView);
        listview.setSelection(currentVal);

    }
}

class LoadStuffAsyncTask extends  AsyncTask<Void, Void, Void>{
    private ProgressDialog pDialog;
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(activity);
        pDialog.setMessage(activity.getString(R.string.loading));
        pDialog.setCancelable(false);
        pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        pDialog.show();
    }


    @Override
    protected Void doInBackground(Void... params) {
        LoadStuff();
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        pDialog.dismiss();
        swipeRefreshLayout.setRefreshing(false);
        listAdapter = new CustomAdapter(activity,momentosGeneral);
        listview.setAdapter(listAdapter);

    }
}
}

这是适配器:

public class CustomAdapter extends BaseAdapter {

//declaration of variables.....

public CustomAdapter(ActionBarActivity activity, List<ParseObject> list) {

    this.activity = activity;
    this.list = list;
}

@Override
public int getCount() {
    return list.size();
}

@Override
public Object getItem(int position) {
    return position;
}

@Override
public long getItemId(int position) {
    return position;
}

private static class ViewHolder{
  //holderfields......
}

@Override
public View getView(final int position, View v, ViewGroup parent) {
  ViewHolder holder;
  if (v == null) {
        v = View.inflate(activity.getApplicationContext(), R.layout.customview, null);
        holder = new ViewHolder();
        holder.profilepicture = (CircularImageView) v.findViewById(R.id.profilepic);
        holder.username = (TextView) v.findViewById(R.id.username);
        holder.picture = (ParseImageView) v.findViewById(R.id.picture);
        holder.container =(LinearLayout)v.findViewById(R.id.container);
        holder.share=(LinearLayout)v.findViewById(R.id.share);
        holder.comment= (TextView) v.findViewById(R.id.comment);
        holder.likes= (TextView) v.findViewById(R.id.likes);
        holder.publishDate =(TextView)v.findViewById(R.id.publisdate);
        holder.liked = (ImageView)v.findViewById(R.id.liked);
        v.setTag(holder);
    }

    holder = (ViewHolder)v.getTag();
    CustomTypography customTypo = new CustomTypography(activity.getApplicationContext());
    holder.username.setTypeface(customTypo.OpenSansSemibold());

    if(list.get(position).getParseUser("User")!=null){
        holder.username.setText(list.get(position).getParseUser("User").getString("name"));
        profilePic = list.get(position).getParseUser("User").getParseFile("profilePic");

        if (profilePic != null) {
            try {
                Drawable drawable = new BitmapDrawable(BitmapFactory.decodeByteArray(profilePic.getData(), 0, profilePic.getData().length));
                holder.profilepicture.setImageDrawable(drawable);
                holder.profilepicture.setDrawingCacheEnabled(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
    else{

        holder.username.setText("");
    }

    final ParseFile picture = list.get(position).getParseFile("picture");
    if (picture != null) {
        try {
            Drawable drawable = new BitmapDrawable(BitmapFactory.decodeByteArray(picture.getData(), 0, picture.getData().length));
            holder.picture.setImageDrawable(drawable);
            holder.picture.setDrawingCacheEnabled(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    else{

    }

    holder.container.setLayoutParams(customLayoutParams);

    holder.comment.setText(capitalizarPrimeraLetra(list.get(postiion).getString("Comment")));
    holder.comment.setTypeface(customTypo.OpenSansRegular());

    final int likes= list.get(position).getInt("Likes");
    if(likes==0|| likes<0){
        holder.likes.setText("");
    }else{
        holder.likes.setText(String.valueOf(likes));
    }

    holder.likes.setTypeface(customTypo.OpenSansLight());


    holder.publishDate.setText(timeBetween(list.get(position).getCreatedAt()));

    ParseQuery<ParseObject> query = ParseQuery.getQuery("LikedPictures");
    query.whereEqualTo("picture", list.get(position));
    query.whereEqualTo("user", currentUser);


    query.findInBackground(new FindCallback<ParseObject>() {
        public void done(List<ParseObject> likelist, ParseException e) {

            if (e == null) {
                if (likelist.size() != 0) {
                    hasLiked = true;
                    holder.liked.setBackground(activity.getApplicationContext().getResources().getDrawable(R.drawable.like));
                    holder.likes.setTextColor(activity.getApplicationContext().getResources().getColor(R.color.red));
                } else {
                    hasLiked = false;
                }
            } else {
                hasLiked = false;
            }

        }
    });
     return v;
}
private String timeBetween(Date date){
    String result="";
    Date parsedPictureDate = null;
    Date parsedCurrentDate=null;
    Date today = new Date();
    SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
    dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
    SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
    try {
        parsedPictureDate= dateFormatLocal.parse(dateFormatGmt.format(date));
        parsedCurrentDate=dateFormatLocal.parse(dateFormatGmt.format(hoy));
    } catch (java.text.ParseException e) {
        result="";
    }

    long milis=parsedCurrentDate.getTime()-parsedPictureDate.getTime();
    final long MILISECS_PER_MINUTE=milis/(60 * 1000);
    final long MILISECS_PER_HOUR=milis/(60 * 60 * 1000);
    final long MILLSECS_PER_DAY=milis/(24 * 60 * 60 * 1000);


    if(milis<60000){
        result="Now";
    }
    if(milis>=60000&&milis<3600000){
        result=MILISECS_PER_MINUTE+" min";

    }
    if(milis>=3600000&&milis<86400000){
        result=MILISECS_PER_HOUR+" h";

    }
    if(milis>=86400000){
        result=MILLSECS_PER_DAY+" d";
    }
    return  result;
}

这是始终在listview

中填充的项目
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical" android:layout_width="match_parent"
    android:background="@android:color/white"
    android:paddingBottom="20dp"
    android:layout_height="match_parent">


    <LinearLayout

        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <LinearLayout

            android:id="@+id/somelayout"
            android:layout_weight="0.5"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginTop="@dimen/margin_16dp_sw600"

            android:layout_marginLeft="5dp"
            android:paddingRight="@dimen/padding_16dp_sw600"
            android:gravity="left"
            android:layout_marginBottom="5dp">

            <customImageView

                android:layout_gravity="center"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:id="@+id/profilepicture"
                app:border_width="0dp"

                />

            <TextView
                android:layout_marginLeft="@dimen/margin_16dp_sw600"
                android:layout_gravity="center"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/username"
                android:textSize="14sp"
                android:gravity="left"
                android:singleLine="true"
                android:minLines="1"
                android:maxLines="1"
                android:lines="1"
                />



        </LinearLayout>

        <LinearLayout

            android:id="@+id/layoutTime"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="right"
            android:layout_weight="0.5"
            android:layout_gravity="center"  >
            <TextView
                android:gravity="right"
                android:id="@+id/publishdate"
                android:layout_marginRight="@dimen/margin_16dp_sw600"
                android:textSize="14sp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"


                />
        </LinearLayout>
    </LinearLayout>

    <LinearLayout
        android:paddingLeft="5dp"

        android:layout_width="wrap_content"
        android:layout_height="wrap_content">


    <LinearLayout
        android:id="@+id/container"
        android:layout_gravity="center"
        android:background="@drawable/border"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"
        >
        <com.parse.ParseImageView

            android:layout_margin="1dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent"

            android:id="@+id/picture" />
    </LinearLayout>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        >

        <LinearLayout
            android:id="@+id/layoutlikes"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="left"
            android:layout_weight="0.5"

            android:layout_gravity="center"  >
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:id="@+id/likes"
                >
                <TextView
                    android:layout_gravity="center"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/numlikes"
                    android:text="0"
                    android:textSize="14sp"
                    android:layout_margin="@dimen/margin_16dp_sw600"
                    />
                <ImageView
                    android:layout_gravity="center"
                    android:layout_marginRight="@dimen/margin_16dp_sw600"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/likepic"
                    android:background="@drawable/like_off"
                    />
            </LinearLayout>
        </LinearLayout>
        <LinearLayout
            android:id="@+id/sharelayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="right"
            android:padding="10dp"
            android:layout_weight="0.5"
            android:layout_marginTop="@dimen/margin_16dp_sw600"
            android:layout_gravity="center"  >
            <ImageView

                android:layout_gravity="center"
                android:layout_marginRight="@dimen/margin_16dp_sw600"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/sharepic"
                android:background="@drawable/ellipsis"
                />
        </LinearLayout>
    </LinearLayout>
    <View

        android:layout_width="match_parent"
        android:layout_height="@dimen/division_2dp_sw_600"
        android:layout_margin="@dimen/margin_16dp_sw600"
        android:background="@color/loading" />
    <TextView

        android:layout_gravity="left"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/comment"

        android:textSize= "14sp"

        android:layout_marginLeft="@dimen/margin_16dp_sw600"
        android:layout_marginRight="@dimen/margin_16dp_sw600"
        />


</LinearLayout>

2 个答案:

答案 0 :(得分:1)

您最大的表现可能是下面的代码。你应该使用某种caching而不是每次解码位图。

if (profilePic != null) {
            try {
                Drawable drawable = new BitmapDrawable(BitmapFactory.decodeByteArray(profilePic.getData(), 0, profilePic.getData().length));
                holder.profilepicture.setImageDrawable(drawable);
                holder.profilepicture.setDrawingCacheEnabled(true);
            } catch (Exception e) {
                e.printStackTrace();
            }

此外,每次调用getView()时,您都在创建一个新的CustomTypography实例。我假设这个类扩展了Typeface,在这种情况下你可以使用在适配器的构造函数中初始化的单个实例。

答案 1 :(得分:1)

以下是一些事项:

在adapter.getView()方法中

1。,移动

 holder = (ViewHolder)v.getTag();

到if / else范围:

if(view ==null){
    //creation of viewHolder
}else{
    holder = (ViewHolder)v.getTag();
}

2. :adapter.getView()中的代码太多,特别是解析查询。您最好通过缓存适配器中每个项目的查询结果,为每个项目调用一次。目前正在调用每个项目在滚动时可见。

3。尝试减少商品xml中的观看次数。 ListView项目中的视图太多会导致内存泄漏和低性能。

4。将manifestAccelerated =“true”添加到清单中的活动可能会有所帮助。

5. 尝试注释滚动侦听器,以确定它是否会降低性能。