我想提供一些背景信息:我目前参与帮助开发的应用是一家公司已经为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>
答案 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. 尝试注释滚动侦听器,以确定它是否会降低性能。