2013-03-16 86 views
0

我开发了一个联系人应用程序。它可以完成普通联系人应用程序应该做的一切。总有改善的机会。我注意到在Android模拟器中,加载联系人图像是在用户定居时开始的,他已经将联系人列表滚动到有可能与他正在寻找的联系人的机会的区域。所以,我试图在我的应用程序副本上实现相同的功能。我已经实现了它。它的运行非常缓慢。正如我所假设的那样,我认为即使应用程序检索到导致严重滞后的图像,应用程序也会多次运行该线程。我知道ASync任务,但出于好奇,并检查是否可以完成,我不希望在这里实现它。以下是MainActivity的源代码。缓慢的应用程序性能

package com.example.contact; 

import java.io.InputStream; 
import java.util.ArrayList; 



import android.net.Uri; 
import android.os.Bundle; 
import android.provider.ContactsContract; 
import android.provider.ContactsContract.Contacts; 
import android.app.ListActivity; 
import android.content.ContentUris; 
import android.content.Context; 
import android.database.Cursor; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.util.Log; 
import android.view.Menu; 
import android.view.View; 
import android.widget.AbsListView; 
import android.widget.ImageView; 
import android.widget.LinearLayout; 
import android.widget.ListView; 

public class MainActivity extends ListActivity { 

    ListView listview; 
    private boolean mPaused; 
    private MyAdapter mAdapter; 
    private View view; 
    private boolean running = false; 
    final private ArrayList<String> con_ids = new ArrayList<String>(); 
    private Context context; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 


     listview = getListView(); 
     context = this; 

     Cursor c = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, 
               null, 
               null, 
               null, 
               ContactsContract.Contacts.DISPLAY_NAME+" ASC"); 


     if(c!=null) 
     { 
      for(c.moveToFirst();!c.isAfterLast();c.moveToNext()){ 
       con_ids.add(c.getString(c.getColumnIndex(ContactsContract.Contacts._ID))); 
      } 
     } 

     mAdapter = new MyAdapter(this, android.R.layout.simple_list_item_1, con_ids); 
     listview.setAdapter(mAdapter); 
     listview.setOnScrollListener(makeScrollListener()); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.activity_main, menu); 
     return true; 
    } 

    public void setEnabled(boolean enabled) { 
     mPaused = !enabled; 
    } 

    private AbsListView.OnScrollListener makeScrollListener() { 
     return new AbsListView.OnScrollListener() { 
      @Override 
      public void onScrollStateChanged(AbsListView absListView, int scrollState) { 
       setEnabled(scrollState != AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 
       running = false; 
      } 

      @Override 
      public void onScroll(AbsListView absListView, int i, int i1, int i2) { 

       String log = ""; 
       Log.d(log, "Scroll First Item" + i); 
       Log.d(log, ""+ listview.getChildCount());   

       final int want = i; 
       running = true; 

       runOnUiThread(new Thread(new Runnable() { 
        int totalChild = listview.getChildCount(); 
        int first = listview.getFirstVisiblePosition() - listview.getHeaderViewsCount(); 
        int toRetrieve = want-first; 
        int id; 
        long con_id; 
        Bitmap thumbnail; 
        final ListView list = listview; 

        @Override 
        public void run() { 
         // TODO Auto-generated method stub 
         while(running) 
         { 
          if(!(toRetrieve<0||toRetrieve>=totalChild)) 
          { 
           id = want+toRetrieve; 
           con_id = Long.valueOf(con_ids.get(id)); 
           Uri ContactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, con_id); 
           InputStream stream = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), ContactUri); 
           thumbnail = BitmapFactory.decodeStream(stream); 
           if(thumbnail == null) 
           { 
            toRetrieve++; 
            continue; 
           } 
           else 
           { 
            View view = list.getChildAt(toRetrieve); 
            if(view == null) 
            { 
             toRetrieve++; 
             continue; 
            } 
            else 
            { 
             ImageView iamge = (ImageView) view.findViewById(R.id.contact_iamge); 
             iamge.setImageBitmap(thumbnail); 
            } 
            toRetrieve++; 
           } 

          } 
          else 
          { 
           running = false; 
          } 
         } 
        } 
       })); 
      } 
     }; 
    } 

} 

代码MyAdapter,

package com.example.contact; 

import java.util.ArrayList; 

import android.content.ContentUris; 
import android.content.Context; 
import android.database.Cursor; 
import android.graphics.drawable.Drawable; 
import android.net.Uri; 
import android.provider.ContactsContract; 
import android.provider.ContactsContract.Contacts; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.webkit.WebView.FindListener; 
import android.widget.ArrayAdapter; 
import android.widget.ImageView; 
import android.widget.ListView; 
import android.widget.TextView; 

public class MyAdapter extends ArrayAdapter<String> { 

    private Context context; 
    private ListView listview; 
    private ArrayList<String> ids; 
    private LayoutInflater infl; 
    private String displayname; 
    private String maindetail; 
    private SimplifiedContact contact; 
    private Drawable drawable; 


    public MyAdapter(Context context, int ResourceId, ArrayList<String> list) 
    { 
     super(context, ResourceId, list); 
     this.context = context; 
     ids = list; 
     infl = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     drawable = context.getResources().getDrawable(R.drawable.person); 
    } 

    static class ViewHolder 
    { 
     public ImageView image; 
     public TextView display_name; 
     public TextView main_detail; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 

     View row = convertView; 
     contact = new SimplifiedContact(context, Long.valueOf(ids.get(position))); 

     if(row == null) 
     { 
      row = infl.inflate(R.layout.single_cell, parent, false); 
      ViewHolder viewHolder = new ViewHolder(); 

      viewHolder.display_name =(TextView) row.findViewById(R.id.disp_name); 
      viewHolder.main_detail = (TextView) row.findViewById(R.id.main_detail); 
      viewHolder.image = (ImageView)row.findViewById(R.id.contact_iamge); 
      row.setTag(viewHolder); 

     } 

     ViewHolder holder = (ViewHolder) row.getTag(); 
     holder.display_name.setText(contact.getDisplayName()); 
     holder.main_detail.setText(contact.getMainDetail()); 
     holder.image.setBackgroundDrawable(drawable); 

     return row; 
    } 


} 

,我想知道,如何滞后可以降低。提前致谢。

+0

前runOnUiThread产生线程()。我使用了普通的线程过程,导致了一个异常,即最初创建视图的主线程可能是唯一修改它的异常。我搜索了解决方案并了解到为了让事情变得更好,我必须在UI线程上运行线程。 – Paras 2013-03-16 22:20:25

+0

那么,我已经在我的应用程序中实现了ASync任务。这只是我不想这样做。所以,基本上,在这个问题中,我是否需要中止onScroll加载概念? – Paras 2013-03-16 22:50:05

回答

0

为什么不尝试在runOnUiThread中创建Thread实例并将其放入字段中,并在onCreate中初始化它。我认为你正在创建几个线程instaces没有用。

public class MainActivity extends ListActivity { 

ListView listview; 
private boolean mPaused; 
private MyAdapter mAdapter; 
private View view; 
private boolean running = false; 
final private ArrayList<String> con_ids = new ArrayList<String>(); 
private Context context; 
Thread uiThread; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 


    listview = getListView(); 
    context = this; 

    Cursor c = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, 
              null, 
              null, 
              null, 
              ContactsContract.Contacts.DISPLAY_NAME+" ASC"); 


    if(c!=null) 
    { 
     for(c.moveToFirst();!c.isAfterLast();c.moveToNext()){ 
      con_ids.add(c.getString(c.getColumnIndex(ContactsContract.Contacts._ID))); 
     } 
    } 

    uiThread = new Thread(new Runnable() { 
     int totalChild = listview.getChildCount(); 
     int first = listview.getFirstVisiblePosition() - listview.getHeaderViewsCount(); 
     int toRetrieve = want-first; 
     int id; 
     long con_id; 
     Bitmap thumbnail; 
     final ListView list = listview; 

     @Override 
     public void run() { 
      // TODO Auto-generated method stub 
      while(running) 
      { 
       if(!(toRetrieve<0||toRetrieve>=totalChild)) 
       { 
        id = want+toRetrieve; 
        con_id = Long.valueOf(con_ids.get(id)); 
        Uri ContactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, con_id); 
        InputStream stream = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), ContactUri); 
        thumbnail = BitmapFactory.decodeStream(stream); 
        if(thumbnail == null) 
        { 
         toRetrieve++; 
         continue; 
        } 
        else 
        { 
         View view = list.getChildAt(toRetrieve); 
         if(view == null) 
         { 
          toRetrieve++; 
          continue; 
         } 
         else 
         { 
          ImageView iamge = (ImageView) view.findViewById(R.id.contact_iamge); 
          iamge.setImageBitmap(thumbnail); 
         } 
         toRetrieve++; 
        } 

       } 
       else 
       { 
        running = false; 
       } 
      } 
     } 
    }); 

    mAdapter = new MyAdapter(this, android.R.layout.simple_list_item_1, con_ids); 
    listview.setAdapter(mAdapter); 
    listview.setOnScrollListener(makeScrollListener()); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.activity_main, menu); 
    return true; 
} 

public void setEnabled(boolean enabled) { 
    mPaused = !enabled; 
} 

private AbsListView.OnScrollListener makeScrollListener() { 
    return new AbsListView.OnScrollListener() { 
     @Override 
     public void onScrollStateChanged(AbsListView absListView, int scrollState) { 
      setEnabled(scrollState != AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 
      running = false; 
     } 

     @Override 
     public void onScroll(AbsListView absListView, int i, int i1, int i2) { 

      String log = ""; 
      Log.d(log, "Scroll First Item" + i); 
      Log.d(log, ""+ listview.getChildCount());   

      final int want = i; 
      running = true; 

      runOnUiThread(uiThread); 
     } 
    }; 
} 

}

+0

我的主要目标是在用户停止滚动时再启动线程,并在再次滚动时再次停止线程。我看不到更好的地方。不过,我欢迎您的建议,请用代码示例说明您的答案,这将有所帮助。 – Paras 2013-03-16 22:17:13

+0

上面的代码并没有真正改变应用程序的任何内容,并且运行速度也很慢,因为它仍然是在UI线程上运行的完全相同的代码。 – 323go 2013-03-16 22:32:08