I'm becoming quite desperate with this issue, and I've been trying all the ideas you all have been posting in other threads.
The problem is that my program makes massive calls to getView() method, and I implemented the Holder paradigm, but it's still horribly slow, maybe someone can enlighten me?
This is my Adapter class:
import java.util.ArrayList;
import android.content.Context;
import android.location.Location;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class IconListViewAdapterPharmacy extends ArrayAdapter<PharmacyListItem>
{
private ArrayList<PharmacyListItem> items;
private Context cont;
private Location l;
public IconListViewAdapterPharmacy(Context cont, int textViewResourceId, ArrayList<PharmacyListItem> items, Location l)
{
super(cont, textViewResourceId, items);
this.cont = cont;
this.items = items;
this.l = l;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
PharmacyListItem o = items.get(position);
ViewHolder holder = new ViewHolder();
if (v == null)
{
LayoutInflater vi = (LayoutInflater)cont.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.icon_row_pharmacy, null);
holder.tt = (TextView) v.findViewById(R.id.pharmacy_row_toptext);
holder.address = (TextView) v.findViewById(R.id.pharmacy_row_address);
holder.distance = (TextView) v.findViewById(R.id.pharmacy_row_distance);
holder.telephone = (TextView) v.findViewById(R.id.pharmacy_row_telephone);
// associate the holder with the view for 开发者_StackOverflow中文版later lookup
v.setTag(holder);
}
else
{
holder = (ViewHolder)convertView.getTag();
}
holder.tt.setText(o.getName());
String add = "" + o.getAddress();
holder.address.setText("" + add.substring(0, add.lastIndexOf(",")));
holder.telephone.setText("" + o.getTelephone());
String distancia = "" + o.getDistance();
if(l != null)
holder.distance.setText("Distancia: " + distancia);
return v;
}
static class ViewHolder
{
TextView tt;
TextView address;
TextView distance;
TextView telephone;
}
}
The class PharmacyListItem:
import android.location.Location;
public class PharmacyListItem
{
private String name;
private double lat;
private double lng;
private String telephone;
private double distance;
public PharmacyListItem(Location l, String name, double lat, double lng , String telephone)
{
this.name = name;
this.lng = lng;
this.lat = lat;
this.telephone = telephone;
Location l2 = new Location(l);
l2.setLatitude(lat);
l2.setLongitude(lng);
distance = l.distanceTo(l2);
}
public String getName()
{
return name;
}
public String getAddress()
{
return GeoLocator.getAddress(lat, lng);
}
public String getTelephone()
{
return telephone;
}
public String getDistance()
{
return (""+distance).substring(0, (""+distance).indexOf(".")) + "m.";
}
public double getDist()
{
return distance;
}
}
Any ideas will be much appreciated!
Thank you all!
EDIT I paste here my .xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip"
android:layout_marginRight="4dip"
android:background="@drawable/bg_detalle_1">
<ImageView
android:id="@+id/arrow2"
android:layout_width="wrap_content"
android:layout_centerVertical="true"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:singleLine="true"
android:ellipsize="marquee"
android:layout_marginRight="4dip"/>
<LinearLayout android:padding="10dip" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/linearLayout3" android:orientation="vertical">
<LinearLayout android:layout_height="wrap_content" android:id="@+id/linearLayout1" android:layout_width="match_parent">
<TextView android:gravity="center" android:textColor="#525252" android:layout_height="fill_parent" android:singleLine="true" android:ellipsize="marquee" android:text="" android:textStyle="bold" android:id="@+id/pharmacy_row_toptext" android:layout_width="wrap_content" android:layout_marginRight="6dip"></TextView>
</LinearLayout>
<LinearLayout android:layout_height="wrap_content" android:id="@+id/linearLayout2" android:layout_width="match_parent">
<TextView android:layout_height="fill_parent" android:text="TextView" android:id="@+id/pharmacy_row_address" android:layout_width="wrap_content" android:layout_marginRight="6dip"></TextView>
</LinearLayout>
<LinearLayout android:layout_height="wrap_content" android:layout_width="match_parent" android:id="@+id/linearLayout5">
<TextView android:gravity="center" android:layout_height="fill_parent" android:text="TextView" android:singleLine="true" android:ellipsize="marquee" android:layout_width="wrap_content" android:id="@+id/pharmacy_row_telephone"></TextView>
</LinearLayout>
<LinearLayout android:layout_gravity="right" android:layout_height="wrap_content" android:id="@+id/linearLayout5" android:layout_width="match_parent">
<TextView android:layout_height="fill_parent" android:text="TextView" android:singleLine="true" android:ellipsize="marquee" android:layout_width="wrap_content" android:id="@+id/pharmacy_row_distance"></TextView>
</LinearLayout>
</LinearLayout>
</LinearLayout>
From the code you have posted, it seems problem is not with your adapter or ListView code. Your are using GeoLocation API calls from your getview method which are known to be slow and resource consuming. Yous should probably look at that part of your code for optimizing. Your adapter and ListView code is absolutely fine and optimized.
This is a really old thread but I discovered a big reason for slow scrolling of ListView.
The android:ellipsize="marquee" attribute has a very big impact on ListView performance. The impact is, in simple words, without it, buttery smooth scrolling but with it, laggy as hell.
I discovered it when I used the Show GPU Overdraw in Developer Settings.
I hope this helps future viewers of this thread.
Instead Of this
public IconListViewAdapterPharmacy(Context cont, int textViewResourceId, ArrayList<PharmacyListItem> items, Location l)
{
super(cont, textViewResourceId, items);
this.cont = cont;
this.items = items;
this.l = l;
}
do this
public IconListViewAdapterPharmacy(Context cont, int textViewResourceId, ArrayList<PharmacyListItem> items, Location l)
{
super(cont, textViewResourceId, items);
this.l = l;
}
Then In getView access items using getItem(position)
instead of items.get(position)
and to get context call getContext()
.
Dont know if that will improve the performance. But no harm in trying. Also this is the correct way.
Edit:
Can get the address and update the UI later like you do if you had a profile image to be downloaded and shown.
String add = "" + o.getAddress();
if (TextUtils.IsEmpty(add)) {
// download the geolocation. pass the position to the downloader thread which will update the item at position with address, after fetching is complete.
new GetAddressTask(position).execute(o);
}
This will free the UI thread to concentrate on displaying listview.
class GetAddressTask extends Asynctask<.......> {
int mPosition = -1;
public void GetAddressTask(int position) {
mPosition = position;
}
String doInBackground(parameters) {
return GeoLocation.getaddress(parameter[0]);
}
void onPostExecute(String result) { // this runs on UI thread.
// use mPosition here.
// update addapter item with this address thats in 'result' variable.
// and call adapter.notifyDatasetInvalidated()
}
You should move ViewHolder holder = new ViewHolder();
to be inside the if(v==null)
section.
Try to drop your type parameter <PharmacyListItem>
in your IconListViewAdapterPharmacy
class. You can always change the type of items
to ArrayList
or to Object[]
and use the constructor
IconListViewAdapterPharmacy(Context context, int resource, Object[] objects){...}
I ran into a similar issue while extending the class
ArrayAdapter<String>
for my custom Adapter
. When I dropped the type parameter <String>
and simply extended ArrayAdapter
, everything ran much faster. I'm not quite sure I understand why though...
精彩评论