2013-03-16 117 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