2013-07-05 4 views
3

AsyncTaskLoader을 사용하는 데 문제가 있습니다. 이 첫 번째 시도는 입니다. ListViewSQLite 데이터베이스에서 로더를 사용합니다.AsyncTaskLoader를 사용하여 ListView 채우기

모든 것이 정상적으로 보입니다. 화면을 회전하면 데이터가 캐시되고 다시 쿼리가 수행되지 않습니다. 그러나 홈 버튼을 누르고 내 앱을 다시 시작하면 데이터가 다시로드됩니다.

: UsuarioUser을 의미한다, 그래서 사용자의 목록과 ListView에을 채우는거야.

public class Main extends SherlockFragmentActivity 
     implements LoaderManager.LoaderCallbacks<ArrayList<Usuario>> { 
    UsuarioAdapter adapter; 
    ListView listView; 
    Database db; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     listView = (ListView) findViewById(R.id.lista); 
     db  = new Database(this); 
     adapter = new UsuarioAdapter(this, new ArrayList<Usuario>()); 
     listView.setAdapter(adapter); 
     getSupportLoaderManager().initLoader(0, null, this); 
    } 

    @Override 
    public Loader<ArrayList<Usuario>> onCreateLoader(int id, Bundle args) { 
     return new UsuariosLoader(this, db); 
    } 

    @Override 
    public void onLoadFinished(Loader<ArrayList<Usuario>> loader, 
          ArrayList<Usuario> usuarios) { 
     //adapter.notifyDataSetChanged(); 
     listView.setAdapter(new UsuarioAdapter(this, usuarios)); 
     // ((BaseAdapter) listView.getAdapter()).notifyDataSetChanged(); 
    } 

    @Override 
    public void onLoaderReset(Loader<ArrayList<Usuario>> loader) { 
     listView.setAdapter(null); 
    } 
} 

// THE LOADER 
class UsuariosLoader extends AsyncTaskLoader<ArrayList<Usuario>> { 
    private ArrayList<Usuario> usuarios; 
    private Database db; 

    public UsuariosLoader(Context context, Database db) { 
     super(context); 
     this.db = db; 
    } 

    @Override 
    protected void onStartLoading() { 
     if (usuarios != null) { 
      deliverResult(usuarios); // Use the cache 
     } 
     forceLoad(); 
    } 

    @Override 
    protected void onStopLoading() { 
     // The Loader is in a stopped state, so we should attempt to cancel the 
     // current load (if there is one). 
     cancelLoad(); 
    } 

    @Override 
    public ArrayList<Usuario> loadInBackground() {    
     db.open(); // Query the database 
     ArrayList<Usuario> usuarios = db.getUsuarios(); 
     db.close(); 
     return usuarios; 
    } 

    @Override 
    public void deliverResult(ArrayList<Usuario> data) { 
     usuarios = data; // Caching 
     super.deliverResult(data); 
    } 

    @Override 
    protected void onReset() { 
     super.onReset(); 
     // Stop the loader if it is currently running 
     onStopLoading(); 
     // Get rid of our cache if it exists 
     usuarios = null; 
    } 

    @Override 
    public void onCanceled(ArrayList<Usuario> data) { 
     // Attempt to cancel the current async load 
     super.onCanceled(data); 
     usuarios = null; 
    } 
} 

그리고 나는이 스 니펫이 잘 수행되지 않았다고 생각합니다. 데이터를 업데이트하는 대신 새 어댑터를 만들고 있습니다.

@Override 
    public void onLoadFinished(Loader<ArrayList<Usuario>> loader, 
          ArrayList<Usuario> usuarios) { 
     //adapter.notifyDataSetChanged(); 
     listView.setAdapter(new UsuarioAdapter(this, usuarios)); 
     //((BaseAdapter) listView.getAdapter()).notifyDataSetChanged(); 
    } 

adapter.notifyDataSetChanged()이 작동하지 않습니까?

기본적으로 내 앱은 중단되지 않지만 앱을 다시 시작할 때마다 내 모든 데이터가 다시로드됩니다.

편집는 :

class UsuarioAdapter extends BaseAdapter { 
    private ArrayList<Usuario> usuarios; 
    private LayoutInflater inflater; 

    public UsuarioAdapter(Context context, ArrayList<Usuario> usuarios) { 
     this.usuarios = usuarios; 
     this.inflater = LayoutInflater.from(context); 
    } 

    @Override 
    public int getCount() { return usuarios.size(); } 
    @Override 
    public Object getItem(int pos) { return usuarios.get(pos); } 
    @Override 
    public long getItemId(int pos) { return pos; } 

    @Override 
    public View getView(int pos, View convertView, ViewGroup arg) { 
     LinearLayout itemView; 
     if (convertView == null) { 
      itemView = (LinearLayout) inflater.inflate(R.layout.list_item, null); 
     } else { 
      itemView = (LinearLayout) convertView; 
     } 

     ImageView avatar = (ImageView) itemView.findViewById(R.id.avatar); 
     TextView nombre = (TextView) itemView.findViewById(R.id.nombre); 
     TextView edad = (TextView)itemView.findViewById(R.id.edad); 

     // Set the image ... TODO 
     nombre.setText(usuarios.get(pos).getNombre()); 
     edad.setText(String.valueOf(usuarios.get(pos).getEdad())); 
     return itemView; 
    } 
} 
+0

내 대답이 맞지 않을 경우 어댑터 코드를 게시하십시오. – Flynn81

+0

@ Flynn81 어댑터 코드가 포함되었습니다. –

+0

귀하의 경우에는 CursorAdapter : BaseAdapter 대신 http://developer.android.com/reference/android/widget/CursorAdapter.html을 사용하고 changeCursor 메소드를 사용하는 것이 좋습니다. – SSemashko

답변

2

해결책을 찾았습니다.

@Override 
    protected void onStartLoading() { 
     if (usuarios != null) { 
      deliverResult(usuarios); // Use cache 
     } else { 
      forceLoad(); 
     } 
    } 

내 원래의 게시물에서 forceLoad는 항상 호출 된 다음 onStartLoading는 유죄이었다. 그것은 else 지점에 있어야합니다.

3

notifyDataSetChanged()에 대한 호출은 어댑터가 사용하는 데이터를 변경하지 않을 것이다 : 이것은 내 어댑터 코드입니다. 어댑터에있는 데이터를 업데이트 한 다음 해당 메소드를 호출해야합니다.

NotifyDataSetChanged()은 어댑터가 뷰를 만들어야한다고 알려주지 만 데이터는 변경하지 않습니다. 너 스스로 처리해야 해. 어댑터 추가 기능에서

:

public void setUsuario(List<Usuario> usuarios) { 
    this.usuarios = usuarios; 
} 

그런 onLoadFinished() 전화 새로운 방법, 다음 notifyDataSetChanged()인치

listView.getAdapter().setUsuario(usuarios); 
listView.getAdapter().notifiyDataSetChanged(); 
+0

그래서'adapter.update (usuarios); adapter.notifyDataSetChanged();'? 감사. –

+0

정확한 답변을 간략한 코드 스 니펫으로 업데이트했습니다. – Flynn81

+0

감사합니다. 하지만 내 첫 번째 문제는 지속됩니다. 라이프 사이클의 특성 때문일 수 있습니다. –