我很好奇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
答案 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的滚动性能也会非常糟糕。
要解决这个问题,下载,解码和位图更改(如果需要)的这些任务应该在另一个线程中发生(例如AsyncTask或HandlerThread)。典型的情况是,当您需要位图时,可以触发AsyncTask或向位图处理线程发出请求。作为线程请求的一部分,应该提供一个侦听器,以便在位图线程上准备好位图时,它将使用侦听器来通知UI线程以更新ImageView。这种实现并非易事,但对于强大的Android应用程序来说是必需的。
一个重要的注意事项:不要将Activity泄漏给其他线程。当发生泄漏并且Android破坏了Activity(由于各种原因经常发生,方向更改是一个),Activity不能被垃圾收集,因为该实例存在于另一个线程中。 Android然后启动活动的新实例,死活动仍然存在。 OOM最终会发生。例如,在为位图线程创建侦听器时,不要将ImageView(因为它具有Activity上下文)作为侦听器的一部分 - 除非您从Activity的onDestroy()中的位图线程中显式删除侦听器。对于AsyncTask,这是不同的 - 只需处理onPostExecute()中的所有ui更改。
应使用缓存来避免重复下载和处理位图。可能的实现将使用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;
}