我阅读了 facebook 开发者博客:https ://www.facebook.com/notes/facebook-engineering/under-the-hood-rebuilding-facebook-for-android/10151189598933920
它说他们正在使用自定义 ListView Recycler 来加快滚动性能。目前,Facebook 原生 Android 应用在滚动和查看大图像方面运行良好。
我想知道如何编写自己的自定义 ListView Recycler?我正在使用 ViewHolder。
这是我的 ArrayAdapter:
public class CampusWallArrayAdapter extends ArrayAdapter<CampusWallModel> {
private final List<CampusWallModel> list;
class ViewHolder {
public ImageView ivThumb;
public TextView display_name;
public ImageView **ivImage**;
public ImageView ivImageBackground;
public TextView time;
public TextView message;
public Button bComment;
public Button bLike;
public Button bMore;
public ImageView ivRedDot;
public ProgressBar pbLoading;
public RelativeLayout bg;
}
public CampusWallArrayAdapter(Context context, List<CampusWallModel> list) {
super(context, R.layout.campuswallrow, list);
this.list = list;
}
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) v.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.campuswallrow, null);
holder = new ViewHolder();
holder.ivThumb = (ImageView) convertView.findViewById(R.id.ivThumb);
holder.display_name = (TextView) convertView.findViewById(R.id.display_name);
**holder.ivImage = (ImageView) convertView.findViewById(R.id.ivImage);**
holder.ivImageBackground = (ImageView) convertView.findViewById(R.id.ivImageBackground);
holder.time = (TextView) convertView.findViewById(R.id.time);
holder.message = (TextView) convertView.findViewById(R.id.message);
holder.bComment = (Button) convertView.findViewById(R.id.bComment);
holder.bLike = (Button) convertView.findViewById(R.id.bLike);
holder.bMore = (Button) convertView.findViewById(R.id.bMore);
holder.ivRedDot = (ImageView) convertView.findViewById(R.id.ivRedDot);
holder.pbLoading = (ProgressBar) convertView.findViewById(R.id.pbLoading);
holder.bg = (RelativeLayout) convertView.findViewById(R.id.bg);
convertView.setTag(holder);
} else {
// Get the ViewHolder back to get fast access to the TextView
// and the ImageView.
holder = (ViewHolder) convertView.getTag();
}
//final ViewHolder holder = (ViewHolder) rowView.getTag();
holder.pbLoading.setVisibility(View.GONE);
holder.ivThumb.setImageBitmap(null);
holder.ivThumb.setImageDrawable(v.getResources().getDrawable(R.drawable.avatar));
**holder.ivImage.setImageBitmap(null);**
holder.ivImageBackground.setBackgroundDrawable(null);
holder.time.setText("");
holder.message.setText("");
holder.bLike.setText("");
holder.bComment.setText("");
holder.bComment.setBackgroundResource(R.drawable.button_comment);
holder.display_name.setText("");
holder.bLike.setVisibility(View.VISIBLE);
holder.bLike.setClickable(true);
holder.bLike.setTextColor(getResources().getColorStateList(R.color.dimgrey3));
holder.bLike.setBackgroundResource(R.drawable.button_like);
holder.ivRedDot.setVisibility(View.GONE);
holder.bMore.setVisibility(View.VISIBLE);
if (list.get(position).display_name == null){
holder.pbLoading.setVisibility(View.VISIBLE);
holder.bLike.setVisibility(View.GONE);
holder.bLike.setClickable(false);
holder.bComment.setVisibility(View.GONE);
holder.bComment.setClickable(false);
} else {
holder.bLike.setTypeface(Fonts.getOpenSansBold(v.getContext()));
holder.bLike.setText(String.valueOf(list.get(position).likes));
if (list.get(position).user_like == -1 || list.get(position).user_like == 0){
holder.bLike.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
list.get(position).likes++;
list.get(position).user_like = 1;
holder.bLike.setClickable(false);
holder.bLike.setText(String.valueOf(list.get(position).likes));
holder.bLike.setTextColor(getResources().getColorStateList(R.color.white1));
holder.bLike.setBackgroundResource(R.drawable.button_liked);
Log.i("like thread invalid", "yes");
listView.invalidateViews();
// ---------------------- new api for campus wall like ---------------------------------
new likeThread(list.get(position).school_thread_id).start();
}
});
} else if (list.get(position).user_like == 1){
holder.bLike.setClickable(false);
holder.bLike.setTextColor(getResources().getColorStateList(R.color.white1));
holder.bLike.setBackgroundResource(R.drawable.button_liked);
}
if (list.get(position).thumb_bitmap != null){
holder.ivThumb.setImageDrawable(null);
holder.ivThumb.setImageBitmap(list.get(position).thumb_bitmap);
holder.ivThumb.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if (!list.get(position).is_anonymous){
Bundle extras = new Bundle();
extras.putInt("user_id", list.get(position).user_id);
Intent i = new Intent(v.getContext(), OthersProfile.class);
i.putExtras(extras);
startActivity(i);
}
}
});
}
if (list.get(position).is_anonymous){
holder.display_name.setTextColor(getResources().getColorStateList(R.color.black1));
} else {
holder.display_name.setTextColor(getResources().getColorStateList(R.color.blue0));
}
holder.display_name.setTypeface(Fonts.getOpenSansBold(v.getContext()));
holder.display_name.setText(list.get(position).display_name);
holder.display_name.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if (!list.get(position).is_anonymous){
Bundle extras = new Bundle();
extras.putInt("user_id", list.get(position).user_id);
Intent i = new Intent(v.getContext(), OthersProfile.class);
i.putExtras(extras);
startActivity(i);
}
}
});
if (list.get(position).image_url != null){
holder.pbLoading.setVisibility(View.VISIBLE);
if (picWidth > 0){
int y = picWidth/2;
if (imageBg == null){
imageBg = new BitmapDrawable(getResources(), NinePatch.getNinePatch(R.drawable.backgroundimage, picWidth, y, v.getContext()));
}
holder.ivImageBackground.setBackgroundDrawable(imageBg);
}
if (list.get(position).bitmap != null){
if (picWidth > 0){
holder.pbLoading.setVisibility(View.GONE);
**holder.ivImage.setImageBitmap(list.get(position).RecBitmap);**
if (!list.get(position).loaded){
//holder.ivImage.startAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.fade)); //Set animation to your ImageView
list.get(position).loaded = true;
}
}
holder.ivImage.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
//Log.i("getWidth", String.valueOf(list.get(position).bitmap.getWidth()) + "/" + String.valueOf((double) picWidth/list.get(position).bitmap.getWidth()));
OohlalaMain.tabs.setVisibility(View.GONE);
rlBigImage.setVisibility(View.VISIBLE);
//tvWords.setText(list.get(position).message);
if (list.get(position).bitmap != null){
ivBigImage.setImageBitmap(Bitmap.createScaledBitmap(list.get(position).bitmap, picWidth, (int) (((double) picWidth/list.get(position).bitmap.getWidth())*list.get(position).bitmap.getHeight()), false));
rlBigImage.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
OohlalaMain.tabs.setVisibility(View.VISIBLE);
rlBigImage.setVisibility(View.GONE);
}
});
pbImageLoading.setVisibility(View.GONE);
}
/*
Bundle extras = new Bundle();
extras.putString("image_url", list.get(position).image_url);
extras.putString("image_words", list.get(position).message);
extras.putInt("picWidth", picWidth);
Intent i = new Intent(v.getContext(), CampusWallImage.class);
i.putExtras(extras);
startActivity(i);
*/
}
});
} else {
if (picWidth > 0){
list.get(position).loaded = false;
}
}
} else {
holder.ivImageBackground.setBackgroundDrawable(null);
}
holder.time.setTypeface(Fonts.getOpenSansLightItalic(v.getContext()));
holder.time.setText(list.get(position).added_time);
holder.message.setTypeface(Fonts.getOpenSansRegular(v.getContext()));
holder.message.setText(list.get(position).message);
holder.bComment.setText(String.valueOf(list.get(position).comment_count));
holder.bComment.setTypeface(Fonts.getOpenSansBold(v.getContext()));
holder.bComment.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Bundle extras = new Bundle();
extras.putInt("school_thread_id", Integer.parseInt(list.get(position).school_thread_id));
extras.putInt("thread_type", thread_type);
Intent i = new Intent(v.getContext(), CampusWallComment.class);
i.putExtras(extras);
startActivity(i);
if (list.get(position).num_unread_comments > 0){
list.get(position).num_unread_comments = 0;
holder.ivRedDot.setVisibility(View.GONE);
holder.bComment.setBackgroundResource(R.drawable.button_comment);
}
}
});
if (list.get(position).num_unread_comments > 0){
holder.bComment.setBackgroundResource(R.drawable.button_comment_unread);
holder.ivRedDot.setVisibility(View.VISIBLE);
}
//Log.i("display thread: ", rowView.toString());
if (Profile.userId != list.get(position).user_id){
holder.bMore.setVisibility(View.GONE);
}
holder.bMore.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
if (Profile.userId == list.get(position).user_id){
showAlertDialog(list.get(position).school_thread_id);
}
}
});
holder.bg.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Bundle extras = new Bundle();
extras.putInt("school_thread_id", Integer.parseInt(list.get(position).school_thread_id));
extras.putInt("thread_type", thread_type);
Intent i = new Intent(v.getContext(), CampusWallComment.class);
i.putExtras(extras);
startActivity(i);
if (list.get(position).num_unread_comments > 0){
list.get(position).num_unread_comments = 0;
holder.ivRedDot.setVisibility(View.GONE);
holder.bComment.setBackgroundResource(R.drawable.button_comment);
}
}
});
}
return convertView;
}
public void showAlertDialog(final String thread_id) {
// TODO Auto-generated method stub
AlertDialog alert = new AlertDialog.Builder(v.getContext()).create();
alert.setTitle(getString(R.string.Delete_Thread));
alert.setMessage(getString(R.string.Warning_This_cannot_be_undone));
alert.setButton(getString(R.string.No), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
alert.setButton2(getString(R.string.Yes), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
RestClient result = null;
try {
if (thread_type == 0){
result = new Rest.request().execute(Rest.CAMPUS_THREAD + thread_id, Rest.OSESS + Profile.sk, Rest.DELETE).get();
} else if (thread_type == 1){
result = new Rest.request().execute(Rest.GROUP_THREAD + thread_id, Rest.OSESS + Profile.sk, Rest.DELETE).get();
}
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ExecutionException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Log.i("delete thread", result.getResponse());
if (result.getResponseCode() == 204){
Toast.makeText(v.getContext(), getString(R.string.The_thread_is_deleted), Toast.LENGTH_SHORT).show();
refreshAfterPost();
}
}
});
alert.show();
}
}
list.get(position).thumb_bitmap 和 list.get(position).RecBitmap 都是位图,第一个是较小的位图,第二个是 1024x1024 的大尺寸位图图像文件。
这是我上面 CampusWallArrayAdapter 的 xml 文件(campuswallrow):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/bg"
android:paddingTop="10dp"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:paddingRight="0dp"
android:background="@drawable/listview_row_bg_state" >
<ImageView
android:id="@+id/ivThumb"
android:layout_width="60dp"
android:layout_height="60dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp" />
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:src="@drawable/avatarframe" />
<TextView
android:id="@+id/display_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="aa"
android:textSize="16dp"
android:textColor="@color/blue0"
android:layout_toRightOf="@+id/ivThumb" >
</TextView>
<TextView
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bb"
android:textColor="@color/black"
android:textSize="13dp"
android:layout_marginRight="10dp"
android:layout_toRightOf="@+id/ivThumb"
android:layout_below="@+id/display_name" >
</TextView>
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="cc"
android:textColor="@color/dimgrey3"
android:textSize="13dp"
android:layout_toRightOf="@+id/ivThumb"
android:layout_below="@+id/message"
android:paddingBottom="10dp" >
</TextView>
<ImageView
android:id="@+id/ivImageBackground"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:layout_below="@+id/time"
android:layout_marginRight="10dp"
android:layout_marginBottom="5dp" >
</ImageView>
<ImageView
**android:id="@+id/ivImage"**
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:layout_below="@+id/time"
android:layout_marginTop="8dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp" />
<ProgressBar
android:id="@+id/pbLoading"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/time"
android:layout_centerInParent="true"
android:layout_marginTop="80dp"
android:visibility="gone" />
<Button
android:id="@+id/bComment"
android:layout_width="65dp"
android:layout_height="35dp"
android:text=""
android:textColor="@color/dimgrey3"
android:textSize="12dp"
android:paddingLeft="20dp"
android:paddingBottom="2dp"
android:background="@drawable/button_comment"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:layout_below="@+id/ivImageBackground" />
<ImageView
android:id="@+id/ivRedDot"
android:layout_width="25dp"
android:layout_height="29dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:layout_marginLeft="45dp"
android:layout_marginTop="-5dp"
android:background="@drawable/navbar_notification_nipple"
android:layout_below="@+id/ivImageBackground"
android:visibility="gone" />
<Button
android:id="@+id/bLike"
android:layout_width="65dp"
android:layout_height="35dp"
android:text=""
android:textColor="@color/dimgrey3"
android:textSize="12dp"
android:paddingLeft="25dp"
android:paddingBottom="2dp"
android:background="@drawable/button_like"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:layout_below="@+id/ivImageBackground"
android:layout_toRightOf="@+id/bComment" />
<Button
android:id="@+id/bMore"
android:layout_width="60dp"
android:layout_height="35dp"
android:layout_alignParentRight="true"
android:background="@drawable/button_context"
android:layout_marginRight="10dp"
android:layout_marginTop="5dp"
android:layout_below="@+id/ivImageBackground" />
<TextView
android:id="@+id/unreadcomment"
android:layout_width="50dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="@drawable/list_unread_ribbon"
android:gravity="center|right"
android:paddingRight="8dp"
android:paddingBottom="3dp"
android:text=""
android:textColor="@color/white1"
android:textSize="13dp"
android:visibility="gone" />
</RelativeLayout>
对于上面的 xml 文件:@+id/ivImage 是我放置主要位图图像的位置。
那么我对 ArrayAdapter 和 ListView 回收器的操作是否正确?有人可以给我一些关于如何使滚动性能更好的提示吗?现在它相当滞后。
谢谢!