2013-03-16 4 views
0

연락처 응용 프로그램을 개발했습니다. 일반 연락처 응용 프로그램에서 수행해야하는 모든 작업을 수행합니다. 항상 개선의 기회가 있습니다. 나는 안드로이드 에뮬레이터에서 사용자가 정착 할 때 연락처 이미지로드가 시작된다는 것을 알았고 접촉 가능성이있는 영역으로 연락처 목록을 스크롤하여 연락처와 접촉 할 가능성이있는 것으로 나타났습니다. 그래서, 내 애플 리케이션 복사본에 동일한 일을 구현하려. 나는 그것을 구현했다. 그것의 달리기는 아주 아주 천천히. 내가 예상했듯이, 응용 프로그램이 큰 지연을 초래하는 이미지를 검색하더라도 스레드가 여러 번 실행되고 있다고 생각합니다. ASync 작업을 알고 있지만 호기심에서 벗어나 그것이 완료 될 수 있는지를 확인하기 위해 여기에 구현하고 싶지 않습니다. MainActivity의 소스 코드는 다음과 같습니다. MyAdapter에 대한느린 응용 프로그램 성능

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; 
          } 
         } 
        } 
       })); 
      } 
     }; 
    } 

} 

코드, 내가 알고 싶은

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

+0

글쎄, 난 내 응용 프로그램에서 ASync 작업을 구현했다. 이번에는 그냥하고 싶지 않습니다. 따라서 기본적으로이 문제에서이 onScroll로드 개념을 중단해야합니까? – Paras

답변

0

runOnUiThread에서 만들고있는 Thread 인스턴스를 가져 와서 onCreate에 초기화하여 필드에 넣으 시지 않는 이유는 무엇입니까? 나는 당신이 쓸모없는 여러개의 스터디를 만들고 있다고 생각한다.

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

+0

위 코드는 UI 스레드에서 실행되는 코드가 정확히 동일하기 때문에 앱에 대해 실제로 변경하지 않으며 느리게 실행됩니다. – 323go