Android - 自定义适配器保持循环

时间:2012-05-15 14:12:51

标签: android android-listview android-custom-view

我很好奇CustomAdapter保持循环同样的事情是正常的吗?例如,我从数据库有3行记录,我想在我的列表中显示它们。一旦我使用customAdapter进行显示,它将循环相同的东西3次。意味着如果我有10行记录,它将循环10次* 10次记录= 100次循环。如果像这样,我的程序肯定会耗尽内存。对此有何解决方案?我附上了我的日志,如下所示。如果你注意到“~~ row id ~~ 0”,它会循环3次。

 public class ViewMsgMain extends ListActivity{

// Retrieve member id from local database
String memberid = FypGeneral.LOGINMEMBERID;
SharedPreferences sp_memberid;
int memid;

String sender_id="", content_type = "", content_path = "", content_id = "", imageaudio_id = "", content_date="";
String over_contentid = "", uploaded_content_id = "", receiver_id = "", read_status = "", 
        sender_member_image="", imageAudio_image="";
InputStream inputstream = null;
StringBuilder stringbuilder = null;
String result = null;

//  retrieved message
String retrieveMsgId[] , uploaded_content_type[];
private LayoutInflater mInflater;
private Vector<RowData> data;
RowData rd;
CustomAdapter adapter;
int pos=1;
String content_type_split[];
String content_date_split[];
String sender_member_image_split[], uploaded_content_id_split[];
String content_path_split[], content_id_split[];
String imageAudio_image_split[];

Bitmap bitmap;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.viewmsglist);

    //===================================================
    // Get member id from local database
    sp_memberid = getSharedPreferences(memberid, MODE_PRIVATE);
    if(sp_memberid.contains("memberid")==true)
    {memid = sp_memberid.getInt("memberid", 0);}
    Log.e("homepage member id == ", "~ "+memid);
    //===================================================

    try{
        //http post
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost("http://localhost/project/viewmessage.php?memberid="+memid);
        //httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); //encode a list of NameValuePair objects suitable for HTTP calls
        HttpResponse response = httpclient.execute(httppost); // to make an HTTPPOST call with the HttpClient
        HttpEntity entity = response.getEntity();
        inputstream = entity.getContent();
    }
    catch(Exception e){
        Toast.makeText(getBaseContext(),e.toString() ,Toast.LENGTH_LONG).show();
    }

    //Convert response to string  
    try
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputstream,"UTF-8"));

        stringbuilder = new StringBuilder();

        String line = null;

        while ((line = reader.readLine()) != null) 
        {
            stringbuilder.append(line + "\n");
        }

        inputstream.close();

        result = stringbuilder.toString();
    }
    catch(Exception e)
    {
        Toast.makeText(getBaseContext(),e.toString() ,Toast.LENGTH_LONG).show();
    }
    //END Convert response to string   
    try{
        JSONArray jArray = new JSONArray(result);
        JSONObject json_data=null;
        if(jArray.length() == 0)
        {
            Toast.makeText(getApplicationContext(), "Tiada mesej", Toast.LENGTH_SHORT).show();
        }
        else
        {
            for(int i=0;i<jArray.length();i++)
            {
                json_data = jArray.getJSONObject(i);
                content_type = content_type + json_data.getString("uploadedcontenttype")+",";
                content_path = content_path+"http://localhost/project/"+(String) json_data.getString("contentpath")+",";
                imageAudio_image = imageAudio_image + json_data.getString("imageaudiopath")+",";
                //r.add(json_data.getString("member_id") + json_data.getString("member_name") + json_data.getString("member_usernamepath"));
                content_id = content_id + json_data.getString("contentid")+",";
                imageaudio_id = imageaudio_id + json_data.getString("imageaudioid")+",";
                content_date = content_date + json_data.getString("contentdate")+",";
                over_contentid = over_contentid + json_data.getString("overallid")+",";
                uploaded_content_id = uploaded_content_id +  json_data.getString("uploadedcontentid")+",";
                sender_id = sender_id +  json_data.getString("senderid")+",";
                receiver_id = receiver_id + json_data.getString("receiverid")+",";
                read_status =read_status + json_data.getString("readstatus")+",";
                sender_member_image = sender_member_image + "http://localhost/project/www/"+json_data.getString("memberimage")+",";
            }
        }
        Log.e("retrieved ", "~ "+content_type + "@ " +  " # "+ content_path + " $ "+ sender_id);
    }
    catch(JSONException e1){
        Toast.makeText(getApplicationContext(), "Tiada mesej", Toast.LENGTH_SHORT).show();
        Log.e("erroe ", e1.toString() );
        //Toast.makeText(getBaseContext(),e1.toString() ,Toast.LENGTH_LONG).show();
    } catch (ParseException e1) {
        Toast.makeText(getBaseContext(),e1.toString() ,Toast.LENGTH_LONG).show();
    }

    // Split the data retrieved from database
    content_type_split = content_type.split(",");
    content_path_split = content_path.split(",");
    content_id_split = content_id.split(",");
    content_date_split = content_date.split(",");
    sender_member_image_split = sender_member_image.split(",");
    uploaded_content_id_split = uploaded_content_id.split(",");
    imageAudio_image_split = imageAudio_image.split(",");

    mInflater = (LayoutInflater) getSystemService(
            Activity.LAYOUT_INFLATER_SERVICE);
    data = new Vector<RowData>();
    for(int i=0;i<content_type_split.length;i++){

        try {
            rd = new RowData(i,content_type_split[i],content_date_split[i]);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        data.add(rd);
    }
    CustomAdapter adapter = new CustomAdapter(this, R.layout.list,
            R.id.title, data);
    setListAdapter(adapter);
    //getListView().setTextFilterEnabled(true);
}

public void onListItemClick(ListView parent, View v, int position,
        long id) {
    // Show details in another page
    Intent viewMsgIntent = new Intent(ViewMsgMain.this, ViewMsgDetails.class);
    viewMsgIntent.putExtra("content_type", content_type_split[position]);
    viewMsgIntent.putExtra("content_path", content_path_split[position]);
    viewMsgIntent.putExtra("sender_member_image", sender_member_image_split[position]);
    viewMsgIntent.putExtra("imageAudio_image", imageAudio_image_split[position]);
    startActivity(viewMsgIntent);
}
private class RowData {
    protected int mId;
    protected String mTitle;
    protected String mDetail;
    RowData(int id,String title,String detail){
        mId=id;
        mTitle = title;
        mDetail=detail;
    }
    @Override
    public String toString() {
        Log.e("rowdata",mId+" "+mTitle+" "+mDetail);
        return mId+" "+mTitle+" "+mDetail;
    }
}
private class CustomAdapter extends ArrayAdapter<RowData> {

    public CustomAdapter(Context context, int resource,
            int textViewResourceId, List<RowData> objects) {               

        super(context, resource, textViewResourceId, objects);
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {   

        ViewHolder holder = null;
        TextView title = null;
        TextView detail = null;
        ImageView i11=null;
        ImageView i112=null;
        RowData rowData= getItem(position);
        Log.e("content_type_split.length ", "## "+content_type_split.length+"   ~~ row id~~   "+ rowData.mId);
        if(null == convertView){
            convertView = mInflater.inflate(R.layout.list, null);
            holder = new ViewHolder(convertView);
            convertView.setTag(holder);
        }
        holder = (ViewHolder) convertView.getTag();
        title = holder.gettitle();
        title.setText(rowData.mTitle);
        detail = holder.getdetail();
        detail.setText(rowData.mDetail);                                                     

        i11=holder.getImage();
        if(content_type_split[rowData.mId].equals("1"))
        {
            i11.setImageResource(R.drawable.imageicon2);
        }
        else if(content_type_split[rowData.mId].equals("2"))
        {
            i11.setImageResource(R.drawable.audioicon2);
        }
        else if(content_type_split[rowData.mId].equals("3"))
        {
            i11.setImageResource(R.drawable.videoicon2);
        }

        Log.e("get view ," , " ~ "+sender_member_image_split[rowData.mId]);

        i112=holder.getImage2();
        try {
            Log.e("enter bitmap ", "yes");
            bitmap = BitmapFactory.decodeStream((InputStream)new URL(sender_member_image_split[rowData.mId]).getContent());
            i112.setImageBitmap(bitmap);

        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return convertView;
    }
    private class ViewHolder {
        private View mRow;
        private TextView title = null;
        private TextView detail = null;
        private ImageView i11=null;
        private ImageView i112=null; 

        public ViewHolder(View row) {
            mRow = row;
        }
        public TextView gettitle() {
            if(null == title){
                title = (TextView) mRow.findViewById(R.id.title);
            }
            return title;
        }     

        public TextView getdetail() {
            if(null == detail){
                detail = (TextView) mRow.findViewById(R.id.detail);
            }
            return detail;
        }
        public ImageView getImage() {
            if(null == i11){
                i11 = (ImageView) mRow.findViewById(R.id.img);
            }
            return i11;
        }

        public ImageView getImage2() {
            if(null == i112){
                i112 = (ImageView) mRow.findViewById(R.id.img2);

            }
            return i112;
        }
    }
}

}

记录

            05-15 21:59:52.660: E/content_type_split.length(7388): ## 3   ~~ row id~~   0
            05-15 21:59:52.670: D/dalvikvm(7388): GC_CONCURRENT freed 352K, 11% free 9318K/10439K, paused 2ms+3ms
            05-15 21:59:52.690: E/get view ,(7388):  ~ http://localhost/project/www/username/kids.jpg
            05-15 21:59:52.690: E/enter bitmap(7388): yes
            05-15 21:59:52.720: W/System.err(7388): Error reading from ./org/apache/harmony/awt/www/content/image/jpeg.class
            05-15 21:59:52.740: E/content_type_split.length(7388): ## 3   ~~ row id~~   1
            05-15 21:59:52.740: E/get view ,(7388):  ~ http://localhost/project/www/username/1_2012512080548_DSC00701.JPG
            05-15 21:59:52.740: E/enter bitmap(7388): yes
            05-15 21:59:52.790: W/System.err(7388): Error reading from ./org/apache/harmony/awt/www/content/image/jpeg.class
            05-15 21:59:52.810: D/dalvikvm(7388): GC_FOR_ALLOC freed 562K, 14% free 9034K/10439K, paused 23ms
            05-15 21:59:52.810: I/dalvikvm-heap(7388): Grow heap (frag case) to 9.477MB for 614416-byte allocation
            05-15 21:59:52.850: D/dalvikvm(7388): GC_FOR_ALLOC freed <1K, 14% free 9633K/11079K, paused 22ms
            05-15 21:59:52.880: E/content_type_split.length(7388): ## 3   ~~ row id~~   2
            05-15 21:59:52.890: E/get view ,(7388):  ~ http://localhost/project/www/username/kids.jpg
            05-15 21:59:52.890: E/enter bitmap(7388): yes
            05-15 21:59:52.930: W/System.err(7388): Error reading from ./org/apache/harmony/awt/www/content/image/jpeg.class
            05-15 21:59:52.950: E/content_type_split.length(7388): ## 3   ~~ row id~~   0
            05-15 21:59:52.950: E/get view ,(7388):  ~ http://localhost/project/www/username/kids.jpg
            05-15 21:59:52.950: E/enter bitmap(7388): yes
            05-15 21:59:52.980: W/System.err(7388): Error reading from ./org/apache/harmony/awt/www/content/image/jpeg.class
            05-15 21:59:52.990: E/content_type_split.length(7388): ## 3   ~~ row id~~   1
            05-15 21:59:52.990: E/get view ,(7388):  ~ http://localhost/project/www/username/1_2012512080548_DSC00701.JPG
            05-15 21:59:52.990: E/enter bitmap(7388): yes
            05-15 21:59:53.040: W/System.err(7388): Error reading from ./org/apache/harmony/awt/www/content/image/jpeg.class
            05-15 21:59:53.060: D/dalvikvm(7388): GC_FOR_ALLOC freed 1064K, 19% free 9034K/11079K, paused 23ms
            05-15 21:59:53.100: E/content_type_split.length(7388): ## 3   ~~ row id~~   2
            05-15 21:59:53.100: E/get view ,(7388):  ~ http://localhost/project/www/username/kids.jpg
            05-15 21:59:53.100: E/enter bitmap(7388): yes
            05-15 21:59:53.130: W/System.err(7388): Error reading from ./org/apache/harmony/awt/www/content/image/jpeg.class
            05-15 21:59:53.170: D/dalvikvm(7388): GC_CONCURRENT freed 820K, 19% free 9033K/11079K, paused 2ms+2ms
            05-15 21:59:53.170: E/content_type_split.length(7388): ## 3   ~~ row id~~   0
            05-15 21:59:53.180: E/get view ,(7388):  ~ http://localhost/project/www/username/kids.jpg
            05-15 21:59:53.180: E/enter bitmap(7388): yes
            05-15 21:59:53.210: W/System.err(7388): Error reading from ./org/apache/harmony/awt/www/content/image/jpeg.class
            05-15 21:59:53.230: E/content_type_split.length(7388): ## 3   ~~ row id~~   1
            05-15 21:59:53.240: E/get view ,(7388):  ~ http://localhost/project/www/username/1_2012512080548_DSC00701.JPG
            05-15 21:59:53.240: E/enter bitmap(7388): yes
            05-15 21:59:53.280: W/System.err(7388): Error reading from ./org/apache/harmony/awt/www/content/image/jpeg.class
            05-15 21:59:53.320: D/dalvikvm(7388): GC_CONCURRENT freed 268K, 13% free 9640K/11079K, paused 3ms+2ms
            05-15 21:59:53.330: E/content_type_split.length(7388): ## 3   ~~ row id~~   2
            05-15 21:59:53.350: E/get view ,(7388):  ~ http://localhost/project/www/username/kids.jpg
            05-15 21:59:53.350: E/enter bitmap(7388): yes

2 个答案:

答案 0 :(得分:1)

请查看此答案

custom listview adapter getView method being called multiple times, and in no coherent order

这不是问题,绝对不能保证调用getView()的顺序也不能保证多少次。

答案 1 :(得分:1)

正如Dheeresh Singh所述,问题不应该是调用getView()多少次。虽然这确实突出了可能的问题。因为getView()可以并且将被无数次调用,所以getView()中的代码需要高效。您对getView()的实现有几个问题。

1)Out of Memory问题(OOM)很可能是由位图引起的。

  • 完成后,位图未正确处理,因为即使退出getView(),它仍然驻留在内存中。这是Android中Bitmaps的本质。调用bitmap.recycle()将释放此内存,并应阻止OOM。

  • 调整或降低位图的分辨率可以提高内存使用率。

2)每次运行getView()时,每次下载并解码所需的位图

  • 这是不可取的,因为这些密集型任务正在UI线程上运行(运行的活动和必须进行的所有ui更改)。如果完成这些任务的时间超过约5秒,Android将标记应用程序停止并发出应用程序无响应(ANR)。即使没有出现ANR,ListView的滚动性能也会非常糟糕。

  • 要解决这个问题,下载,解码和位图更改(如果需要)的这些任务应该在另一个线程中发生(例如AsyncTaskHandlerThread)。典型的情况是,当您需要位图时,可以触发AsyncTask或向位图处理线程发出请求。作为线程请求的一部分,应该提供一个侦听器,以便在位图线程上准备好位图时,它将使用侦听器来通知UI线程以更新ImageView。这种实现并非易事,但对于强大的Android应用程序来说是必需的。

  • 一个重要的注意事项:不要将Activity泄漏给其他线程。当发生泄漏并且Android破坏了Activity(由于各种原因经常发生,方向更改是一个),Activity不能被垃圾收集,因为该实例存在于另一个线程中。 Android然后启动活动的新实例,死活动仍然存在。 OOM最终会发生。例如,在为位图线程创建侦听器时,不要将ImageView(因为它具有Activity上下文)作为侦听器的一部分 - 除非您从Activity的onDestroy()中的位图线程中显式删除侦听器。对于AsyncTask,这是不同的 - 只需处理onPostExecute()中的所有ui更改。

    Memory leakage in event listener

  • 应使用缓存来避免重复下载和处理位图。可能的实现将使用LruCache作为内存缓存,使用DiskLruCache作为磁盘缓存。

    http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

3)ViewHolder使用。

  • 我不确定在其ViewHolder中引用'convertView'是否有用。这个循环引用的唯一用途是实现getter,尽管这对于快速执行getView()来说效率稍低。这将是ViewHolder作为Activity的内部类而不是CustomAdapter的典型实现。

    private class CustomAdapter extends ArrayAdapter<RowData> {
    
        public CustomAdapter(Context context, int resource,
                int textViewResourceId, List<RowData> objects) {               
    
            super(context, resource, textViewResourceId, objects);
        }
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {   
    
            ViewHolder holder = null;
            RowData rowData= getItem(position);
            Log.e("content_type_split.length ", "## "+content_type_split.length+"   ~~ row id~~   "+ rowData.mId);
            if(null == convertView){
                convertView = mInflater.inflate(R.layout.list, null);
                holder = new ViewHolder(convertView);
                convertView.setTag(holder);
                holder.title = (TextView) convertView.findViewById(R.id.title);
                holder.detail = (TextView) convertView.findViewById(R.id.detail);
                holder.i11 = (ImageView) convertView.findViewById(R.id.img);
                holder.i112 = (ImageView) convertView.findViewById(R.id.img2);
    
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
    
            holder.title.setText(rowData.mTitle);
            holder.detail.setText(rowData.mDetail);                                                     
    
            if(content_type_split[rowData.mId].equals("1"))
            {
                holder.i11.setImageResource(R.drawable.imageicon2);
            }
            else if(content_type_split[rowData.mId].equals("2"))
            {
                holder.i11.setImageResource(R.drawable.audioicon2);
            }
            else if(content_type_split[rowData.mId].equals("3"))
            {
                holder.i11.setImageResource(R.drawable.videoicon2);
            }
    
            Log.e("get view ," , " ~ "+sender_member_image_split[rowData.mId]);
    
    
            try {
                Log.e("enter bitmap ", "yes");
                bitmap = BitmapFactory.decodeStream((InputStream)new URL(sender_member_image_split[rowData.mId]).getContent());
                holder.i112.setImageBitmap(bitmap);
    
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            return convertView;
        }
    }
    
    private class ViewHolder {
        TextView title = null;
        TextView detail = null;
        ImageView i11=null;
        ImageView i112=null;
    }