我试图看看滚动时有时候我的listview jerk是什么,有时它很糟糕,特别是当应用程序首次启动时。
我所有的条件都是必要的,除非有一些我不知道的事情(极有可能)。 我没有在单独的线程上运行某些任务,因为它们依赖于我从后端接收的数据(我编码两者,因此也欢迎后端建议)。产品处于测试阶段,但确实需要让它稍微平滑一些。我压缩图像,它们有点长,但不是问题,因为当我从设备上传图像时,我还包括图像的宽度和高度,并将其发送到后端。加载列表时会返回这些尺寸。
我想知道的一件事是,计算/转换特定设备屏幕的尺寸是否会导致轻微的延迟。不确定该任务的资源密集程度如何,但没有它(不知道尺寸,每行将开始平坦然后扩展到实际图片大小,这将导致列表跳转,所以我不能运行该计算在背景上。)
基本上滚动并不坏,但我需要以某种方式改进它。
这是我的适配器:
public class VListAdapter extends BaseAdapter {
ViewHolder viewHolder;
private boolean isItFromProfile;
/**
* fields For number formating, ex. 1000
* would return 1k in the format method
*/
private static final NavigableMap<Long, String> suffixes = new TreeMap<>();
static {
suffixes.put(1_000L, "k");
suffixes.put(1_000_000L, "M");
suffixes.put(1_000_000_000L, "G");
suffixes.put(1_000_000_000_000L, "T");
suffixes.put(1_000_000_000_000_000L, "P");
suffixes.put(1_000_000_000_000_000_000L, "E");
}
private Context mContext;
private LayoutInflater mInflater;
private ArrayList<Post> mDataSource;
private static double lat;
private static double lon;
public VListAdapter(Context context, ArrayList<Post> items) {
mContext = context;
mDataSource = items;
//mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
isItFromProfile = false;
mInflater = LayoutInflater.from(context);
}
public VListAdapter() {
}
public VListAdapter(Context baseContext, ArrayList<Post> posts, boolean b) {
mContext = baseContext;
mDataSource = posts;
//mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
isItFromProfile = b;
mInflater = LayoutInflater.from(baseContext);
}
public void addElement(Post post) {
mDataSource.add(0, post);
this.notifyDataSetChanged();
}
@Override
public int getCount() {
return mDataSource.size();
}
@Override
public Object getItem(int position) {
return mDataSource.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
int limit = Math.min(position + 4, getCount());
for (int i = position; i < limit; i++) {
Glide.with(mContext).load(((Post) getItem(i)).getFilename().toString()).preload();
}
// StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads()
// .detectDiskWrites().detectNetwork()
// .penaltyLog().build());
View rowView = convertView;
if (rowView == null) {
viewHolder = new ViewHolder();
rowView = mInflater.inflate(R.layout.mylist, parent, false);
viewHolder.titleTextView = (TextView) rowView.findViewById(R.id.usernameinlist);
viewHolder.timeago = (TextView) rowView.findViewById(R.id.timeago);
//viewHolder.sharebutton = (ImageView) rowView.findViewById(R.id.sharebutton);
viewHolder.likesTextView = (TextView) rowView.findViewById(R.id.likestext);
viewHolder.viewcount = (TextView) rowView.findViewById(R.id.viewcount);
viewHolder.distance = (TextView) rowView.findViewById(R.id.distance);
viewHolder.footprints = (TextView) rowView.findViewById(R.id.footprintcount);
viewHolder.postText = (TextView) rowView.findViewById(R.id.posttext);
viewHolder.profilePic = (ImageView) rowView.findViewById(R.id.profilethumb);
viewHolder.caption = (TextView) rowView.findViewById(R.id.captiontext);
viewHolder.moremenu = (ImageView) rowView.findViewById(R.id.dots);
viewHolder.likesPic = (ImageView) rowView.findViewById(R.id.likeimage);
viewHolder.mapitPic = (ImageView) rowView.findViewById(R.id.mapimage);
viewHolder.playbutton = (ImageView) rowView.findViewById(R.id.playbutton);
viewHolder.videoThumb = (ImageView) rowView.findViewById(R.id.videothumb);
viewHolder.listphoto = (ImageView) rowView.findViewById(R.id.listphoto);
viewHolder.rainbow = (ImageView) rowView.findViewById(R.id.rainbow);
rowView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) rowView.getTag();
}
final Post post = (Post) getItem(position);
int color = Color.parseColor("#dddddd");
viewHolder.likesPic.setColorFilter(color);
viewHolder.mapitPic.setColorFilter(color);
viewHolder.moremenu.setColorFilter(color);
if (Hawk.count() == 0)
initHawkWithDataFromServer();
if (isItFromProfile) {
viewHolder.profilePic.setVisibility(View.GONE);
viewHolder.titleTextView.setVisibility(View.GONE);
viewHolder.distance.setVisibility(View.GONE);
}
viewHolder.titleTextView.setText(post.getUsername());
PrettyTime prettyTime = new PrettyTime();
DateTime dateTime = new DateTime(post.getUploadDate().get$date());
viewHolder.timeago.setText(prettyTime.format(dateTime.toDate()));
viewHolder.likesTextView.setText(String.valueOf(format(post.getLikes())));
viewHolder.footprints.setText(String.valueOf(format(post.getLocation().size() - 1)));
//don't display 0 if there are no likes, just show heart icon
if (viewHolder.likesTextView.getText().equals("0"))
viewHolder.likesTextView.setVisibility(View.GONE);
else
viewHolder.likesTextView.setVisibility(View.VISIBLE);
//don't display 0 if there are no footprints
if (viewHolder.footprints.getText().equals("0"))
viewHolder.footprints.setVisibility(View.GONE);
else
viewHolder.footprints.setVisibility(View.VISIBLE);
double[] loc = post.getLocation().get(0);
viewHolder.distance.setText("~" + PostListFragment.distance(loc[0], loc[1], 'M') + " Miles");
if (post.getViews() != null)
viewHolder.viewcount.setText(format(post.getViews()) + (post.getViews() == 1 ? " View" : " Views"));
String profilePictureS3Url = "https://s3-us-west-2.amazonaws.com/moleheadphotos/" + post.getUsername()
+ ".jpg";
String filename = post.getS3link();
final String videoThumbURL = "https://s3-us-west-2.amazonaws.com/moleheadphotos/" + filename;
Glide.with(mContext).load(profilePictureS3Url).asBitmap().centerCrop().into(new BitmapImageViewTarget(viewHolder.profilePic) {
@Override
protected void setResource(Bitmap resource) {
RoundedBitmapDrawable circularBitmapDrawable =
RoundedBitmapDrawableFactory.create(mContext.getResources(), resource);
circularBitmapDrawable.setCircular(true);
viewHolder.profilePic.setImageDrawable(circularBitmapDrawable);
}
});
int height = ((Post) getItem(position)).getHeight();
int width = ((Post) getItem(position)).getWidth();
if (height != 0 && width != 0) {
ViewGroup.LayoutParams params = viewHolder.listphoto.getLayoutParams();
Resources r = mContext.getResources();
height = (int) getHeight(height, width);
params.height = height;
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
viewHolder.listphoto.setLayoutParams(params);
} else {
ViewGroup.LayoutParams params = viewHolder.listphoto.getLayoutParams();
params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
viewHolder.listphoto.setLayoutParams(params);
}
if (post.getType() == null) {
Glide.clear(viewHolder.listphoto);
viewHolder.listphoto.setVisibility(View.GONE);
//Glide.clear(viewHolder.listphoto);
viewHolder.videoThumb.setVisibility(View.VISIBLE);
viewHolder.rainbow.setVisibility(View.VISIBLE);
Glide.with(mContext).load(videoThumbURL).fitCenter()
.diskCacheStrategy(DiskCacheStrategy.ALL).dontAnimate().into(viewHolder.videoThumb);
viewHolder.playbutton.setVisibility(View.VISIBLE);
}
if (post.getType() != null) {
if (post.getType().equals("video")) {
viewHolder.playbutton.setVisibility(View.VISIBLE);
Glide.clear(viewHolder.listphoto);
viewHolder.listphoto.setVisibility(View.GONE);
Glide.clear(viewHolder.postText);
viewHolder.postText.setVisibility(View.GONE);
viewHolder.videoThumb.setVisibility(View.VISIBLE);
viewHolder.rainbow.setVisibility(View.VISIBLE);
Glide.with(mContext).load(videoThumbURL).fitCenter()
.diskCacheStrategy(DiskCacheStrategy.ALL).dontAnimate().into(viewHolder.videoThumb);
}
if (post.getType().equals("image")) {
Glide.clear(viewHolder.videoThumb);
viewHolder.videoThumb.setVisibility(View.GONE);
viewHolder.rainbow.setVisibility(View.GONE);
Glide.clear(viewHolder.playbutton);
viewHolder.playbutton.setVisibility(View.GONE);
Glide.clear(viewHolder.postText);
viewHolder.postText.setVisibility(View.GONE);
viewHolder.listphoto.setVisibility(View.VISIBLE);
viewHolder.listphoto.setBottom(0);
Glide.with(mContext).load(post.getFilename().toString())
.diskCacheStrategy(DiskCacheStrategy.ALL).dontAnimate()
.into(viewHolder.listphoto);
}
if (post.getType().equals("text")) {
Glide.clear(viewHolder.videoThumb);
viewHolder.videoThumb.setVisibility(View.GONE);
viewHolder.rainbow.setVisibility(View.GONE);
Glide.clear(viewHolder.playbutton);
viewHolder.playbutton.setVisibility(View.GONE);
Glide.clear(viewHolder.listphoto);
viewHolder.listphoto.setVisibility(View.GONE);
viewHolder.postText.setVisibility(View.VISIBLE);
viewHolder.postText.setText(post.getText());
}
}
if (Hawk.contains("liked" + post.getId().get$oid())) {
viewHolder.likesPic.clearColorFilter();
Glide.with(mContext).load(R.drawable.heartroundorange).into(viewHolder.likesPic);
((ImageView) viewHolder.likesPic).setColorFilter(Color.parseColor("#ff3a6f"));
} else {
Glide.with(mContext).load(R.drawable.heartroundgray).diskCacheStrategy(DiskCacheStrategy.ALL)
.into(viewHolder.likesPic);
}
if (Hawk.contains("mapped" + post.getId().get$oid())) {
viewHolder.mapitPic.clearColorFilter();
((ImageView) viewHolder.mapitPic).setImageResource(R.drawable.dropmaincolororange);
((ImageView) viewHolder.mapitPic).setColorFilter(Color.parseColor("#444444"));
} else {
Glide.with(mContext).load(R.drawable.dropdarkgray).diskCacheStrategy(DiskCacheStrategy.ALL)
.into(viewHolder.mapitPic);
}
if (!Hawk.contains("mapped" + post.getId().get$oid())) {
viewHolder.mapitPic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Hawk.put("mapped" + post.getId().get$oid(), 1);
((ImageView) viewHolder.mapitPic).setImageResource(R.drawable.dropmaincolororange);
viewHolder.footprints.setText(String.valueOf(post.getLocation().size() + 1));
post.getLocation().add(new double[]{PostListFragment.lon, PostListFragment.lat});
notifyDataSetChanged();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
postMappedToServer(post.getId().get$oid());
}
});
t.start();
TastyToast.makeText(mContext, "Post dropped off here.", TastyToast.LENGTH_SHORT, TastyToast.CONFUSING);
}
});
} else {
viewHolder.mapitPic.setClickable(false);
}
if (!Hawk.contains("liked" + post.getId().get$oid())) {
viewHolder.likesPic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Hawk.put("liked" + post.getId().get$oid(), 1);
viewHolder.likesPic.setClickable(false);
((ImageView) viewHolder.likesPic).setImageResource(R.drawable.heartroundorange);
viewHolder.likesTextView.setText(String.valueOf(post.getLikes() + 1));
post.setLikes(post.getLikes() + 1);
notifyDataSetChanged();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
postLikeToServer(post);
}
});
t.start();
}
});
} else {
viewHolder.likesPic.setClickable(false);
}
if (post.getType() == null || post.getType().equals("video"))
viewHolder.videoThumb.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (VListAdapter.this.mContext instanceof ProfileFeed) {
((ProfileFeed) VListAdapter.this.mContext).closeActivity();
}
Intent broadcast = new Intent();
broadcast.setAction("com.molehead.openout.POST");
broadcast.putExtra("postId", post.getFilename().toString());
broadcast.putExtra("hawkId", post.getId().get$oid());
broadcast.putExtra("s3link", post.getS3link());
broadcast.putExtra("username", post.getUsername());
if (Hawk.contains("liked" + post.getId().get$oid()))
broadcast.putExtra("liked", "yes");
else
broadcast.putExtra("liked", "no");
broadcast.putExtra("likecount", post.getLikes().toString());
App.post = post;
LocalBroadcastManager.getInstance(mContext.getApplicationContext()).sendBroadcast(broadcast);
}
});
viewHolder.moremenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
PopupMenu popup = new PopupMenu(mContext.getApplicationContext(), viewHolder.moremenu, Gravity.CENTER);
//Inflating the Popup using xml file
popup.getMenuInflater().inflate(R.menu.menu_main, popup.getMenu());
//registering popup with OnMenuItemClickListener
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_share:
String postId = post.getId().get$oid();
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
String shareBody = postId + ".jpg"; //https://openout.herokuapp.com/posts/" + postId;
String shareSub = "Shared via Molehead";
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, shareSub);
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
sharingIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Intent new_intent = Intent.createChooser(sharingIntent, "Share");
new_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.getApplicationContext().startActivity(new_intent);
break;
}
return true;
}
});
popup.show();
}
});
return rowView;
}
private void initHawkWithDataFromServer() {
SharedPreferences settings = mContext.getApplicationContext().getSharedPreferences("userinfo", 0);
String username = settings.getString("username", "ok");
String password = settings.getString("password", "ok");
LoginService loginService =
ServiceGenerator.createService(LoginService.class, username, password);
final Call<List<Post>> call = loginService.getLikes(username);
Log.i("lonlat", String.valueOf(lon) + " and " + String.valueOf(lat));
call.enqueue(new Callback<List<Post>>() {
@Override
public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
ArrayList<Post> posts = new ArrayList<>();
posts = (ArrayList<Post>) response.body();
if (!posts.isEmpty())
for (Post p : posts) {
Hawk.put("liked" + p.getId().get$oid(), 1);
}
}
@Override
public void onFailure(Call<List<Post>> call, Throwable t) {
}
});
}
private void postMappedToServer(String oid) {
SharedPreferences settings = mContext.getSharedPreferences("userinfo", 0);
String username = settings.getString("username", "ok");
String password = settings.getString("password", "ok");
LoginService loginService =
ServiceGenerator.createService(LoginService.class, username, password);
Log.i("postlistfraglat", String.valueOf(PostListFragment.lat));
Call<ResponseBody> call = loginService.addLocation(oid, PostListFragment.lon, PostListFragment.lat);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful())
Log.i("mapped", "success");
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
}
public void postLikeToServer(Post post) {
SharedPreferences settings = mContext.getSharedPreferences("userinfo", 0);
String username = settings.getString("username", "ok");
String password = settings.getString("password", "ok");
LoginService loginService =
ServiceGenerator.createService(LoginService.class, username, password);
Call<ResponseBody> call = loginService.like(post, 1, username);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
try {
Log.i("call", response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.i("MFEED", "like request failed");
}
});
}
public static String format(long value) {
//Long.MIN_VALUE == -Long.MIN_VALUE so we need an adjustment here
if (value == Long.MIN_VALUE) return format(Long.MIN_VALUE + 1);
if (value < 0) return "-" + format(-value);
if (value < 1000) return Long.toString(value); //deal with easy case
Map.Entry<Long, String> e = suffixes.floorEntry(value);
Long divideBy = e.getKey();
String suffix = e.getValue();
long truncated = value / (divideBy / 10); //the number part of the output times 10
boolean hasDecimal = truncated < 100 && (truncated / 10d) != (truncated / 10);
return hasDecimal ? (truncated / 10d) + suffix : (truncated / 10) + suffix;
}
static class ViewHolder {
private TextView titleTextView;
private TextView timeago;
private TextView likesTextView;
private TextView viewcount;
private TextView distance;
private TextView footprints;
private ImageView profilePic;
private ImageView moremenu;
private ImageView likesPic;
private ImageView mapitPic;
private ImageView rainbow;
//private ImageView sharebutton;
private TextView caption;
private ImageView listphoto;
private ImageView videoThumb;
private ImageView playbutton;
private TextView postText;
private Post post;
}
private float getHeight(float height, float width) {
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
return (height * size.x / width);
}
}
答案 0 :(得分:6)
由于适配器中存在大量代码,因此无法指出特定问题。但有一件事是肯定的 - 在这种情况下切换到RecyclerView
无法帮助你。
适配器不应包含业务逻辑 - 它们只应该适应&#34;将对象输入到基础视图。在您的情况下,似乎适配器执行计算,生成新线程,执行网络请求等。
您需要重构代码,以使适配器与此类似:
public class PostsListAdapter extends ArrayAdapter<Post> {
private Context mContext;
public PostsListAdapter(Context context, int resource) {
super(context, resource);
mContext = context;
}
public void bindPosts(List<Post> posts) {
clear();
addAll(posts);
notifyDataSetChanged();
}
@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
// assign new View to convertView
// create new ViewHolder
// set ViewHolder as tag of convertView
// set listeners
} else {
// get a reference to existing ViewHolder
}
// populate ViewHolder's elements with data from getItem(position)
// kick off asynchronous loading of images
// NOTE: no calculations allowed here - just simple bidding of data to Views
return convertView;
}
}
您的代码需要以这样的方式构建,即在将新数据绑定到ListView
之前执行的数据的计算和转换以及传递给Post
的对象的业务逻辑{1}}方法已包含上述计算和转换的结果。
适配器只是&#34;适应&#34;从bindPosts()
到Posts
的最终数据 - 仅此而已。
如果你现在时间不够短,只需要让它工作&#34;,那么我将首先删除产生新线程并发出网络请求的逻辑。看看这是否会提高性能。
答案 1 :(得分:4)
RecyclerView
,这在废弃视图或回收方面效率更高。如果项目是静态的,我们也可以启用优化,并且不会更改以实现更顺畅的滚动:
recyclerView.setHasFixedSize(true);
创建意向服务并在api请求,业务规则,数据修改完成时将BroadcastReceiver
注册为数据返回回调或错误回调。使用同步调用提前执行initHawkWithDataFromServer()
并在从api获取结果后继续修改或应用业务逻辑。之后,创建新适配器或更新现有适配器数据集。
将以下所有数据计算或数据值格式化逻辑从适配器getView()
移至上述意向服务。
您可以为现有的Post pojo添加更多getter和setter。
DateTime dateTime = new DateTime(post.getUploadDate().get$date());
viewHolder.timeago.setText(prettyTime.format(dateTime.toDate()));
viewHolder.likesTextView.setText(String.valueOf(format(post.getLikes())));
viewHolder.footprints.setText(String.valueOf(format(post.getLocation().size)) - 1)));
Post{
//Your existing property
@Expose(serialize = false, deserialize = false)
//equals neither serialize nor deserialize or
private DateTime uploadedDateTime;
//etc. prettyTime.format, String.valueOf
}
删除不必要的反射:
GsonBuilder builder = new GsonBuilder();
builder.excludeFieldsWithoutExposeAnnotation();
Gson gson = builder.create();
new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson)).build();
它适用于您的改造服务创建类。
您还可以使用transient(private transient DateTime uploadedDateTime;
)
移除
public void addElement(Post post) { mDataSource.add(0, post);
this.notifyDataSetChanged();}
如果您需要通知是否插入,删除了一个或多个项目,请使用以下内容:
notifyItemChanged(int)
notifyItemInserted(int)
notifyItemRemoved(int)
notifyItemRangeChanged(int, int)
notifyItemRangeInserted(int, int)
notifyItemRangeRemoved(int, int)
我们可以从活动或片段中使用这些:
//Add a new contact
items.add(0, new Post("Barney"));
//Notify the adapter that an item was inserted at position 0
adapter.notifyItemInserted(0);
以上方法效率更高。每次我们想要添加或删除RecyclerView
中的项目时,我们都需要明确地通知适配器事件。与ListView
适配器不同,RecyclerView
适配器不应依赖notifyDataSetChanged()
,因为应使用更细粒度的操作。 See the API documentation for more details
此外,如果您打算更新现有列表,请确保在进行任何更改之前获取当前项目数。例如,应该调用适配器上的getItemCount()
来记录将要更改的第一个索引。
// record this value before making any changes to the existing list
int curSize = adapter.getItemCount(); // replace this line with wherever you get new records
ArrayList<Post> newItems = Post.createPostsList(20);
// update the existing list
items.addAll(newItems);
// curSize should represent the first element that got added
// newItems.size() represents the itemCount
adapter.notifyItemRangeInserted(curSize, newItems.size());
差异化更大
在支持库的v24.2.0中添加了一个新的DiffUtil
类,以帮助计算旧列表和新列表之间的差异。 Details
创建颜色作为类成员
int color = Color.parseColor("#dddddd");
在Post pojo中写View.GONE
或View.VISIBLE
,如果是IntentService,它将在Retrofit的后台线程中执行。在json中尝试api return boolean而不是&#34; 0&#34; as String。
将以下全部内容移至IntentService //如果没有喜欢,请不要显示0,只显示心形图标 if(viewHolder.likesTextView.getText()。equals(&#34; 0&#34;)) viewHolder.likesTextView.setVisibility(View.GONE); 其他 viewHolder.likesTextView.setVisibility(View.VISIBLE);
//don't display 0 if there are no footprints
if (viewHolder.footprints.getText().equals("0"))
viewHolder.footprints.setVisibility(View.GONE);
else
viewHolder.footprints.setVisibility(View.VISIBLE);
double[] loc = post.getLocation().get(0);
viewHolder.distance.setText("~" + PostListFragment.distance(loc[0], loc[1], 'M') + " Miles");
所有字符串连接也在Post或IntnetService中,如:
String profilePictureS3Url = "https://s3-us-west-2.amazonaws.com/moleheadphotos/" + post.getUsername() + ".jpg";
您也可以提前创建一次彩色滤镜。从listview中删除滚动条,因为它计算高度以显示滚动条。
答案 2 :(得分:1)
这里需要改进的东西太多了。以下是一些例子。
我看到了这个
if (Hawk.count() == 0)
initHawkWithDataFromServer();
我相信在列表出现的时候会多次调用initHawkWithDataFromServer方法。
此活动只能在创建活动时完成。
Glide.with(mContext).load(videoThumbURL).fitCenter()
但是你应该首先重构代码,将逻辑移到另一个类。尝试删除一些这样的代码(它应该通过使用一些布局属性来完成)
ViewGroup.LayoutParams params = viewHolder.listphoto.getLayoutParams();
Resources r = mContext.getResources();
height = (int) getHeight(height, width);
params.height = height;
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
viewHolder.listphoto.setLayoutParams(params);