2012-12-17 71 views
2

我有一個可擴展列表,包含一個自定義適配器,兩個遊標(來自基本可擴展列表適配器)和一個內容提供程序。使用內容觀察器刷新可擴展列表(Android)

現在,我的主要目標是在插入帶有意圖調用的活動的新數據後,刷新此可擴展列表。我正在嘗試Content Observer,但沒有成功,因爲沒有刷新完成。

我把相關的代碼(我認爲)。非常感謝你。

public class ActPlacesManagement extends Activity{ 
private static final int DELETE_ID = Menu.FIRST; 

private static final String TAG = null; 

public Cursor mPlacesCursor; 
public Cursor mBoxesCursor; 
ExpandableListView lstCategorias; 
AdpPlacesManagement adapter; 
String message, message1, message2; 
String novo_local, nova_caixa; 
Button btnNewPlace, btnNewBox; 
Handler handler; 

private static final String[] PROJECTION_PLACES = new String[] { 
    ProvPersonalArchive.KEY_ROWID_PLACES, 
    ProvPersonalArchive.KEY_DESIG_PLACES, 
}; 

private static final String[] PROJECTION_BOXES = new String[] { 
    ProvPersonalArchive.KEY_ROWID_BOXES, 
    ProvPersonalArchive.KEY_DESIG_BOXES, 
    ProvPersonalArchive.KEY_PLACE_BOXES, 
}; 



protected void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 
    setContentView(R.layout.act_places_management);  

    mPlacesCursor = getContentResolver().query(ProvPersonalArchive.CONTENT_URI_PLACES, 
      PROJECTION_PLACES, null, null, null); 

    mBoxesCursor = getContentResolver().query(ProvPersonalArchive.CONTENT_URI_BOXES, 
      PROJECTION_BOXES, null, null, null); 



    lstCategorias = (ExpandableListView)this.findViewById(R.id.expandableGestaoCategorias); 

    adapter = new AdpPlacesManagement(this, mPlacesCursor, mBoxesCursor, this);  

    lstCategorias.setAdapter(adapter); 

    lstCategorias.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { 

     @Override 
     public boolean onGroupClick(ExpandableListView parent, View v, 
       int groupPosition, long id) { 
      return lstCategorias_onGroupClick(parent, v, groupPosition, id); 
     } 
    }); 

    lstCategorias.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { 

     @Override 
     public boolean onChildClick(ExpandableListView parent, View v, 
       int groupPosition, int childPosition, long id) { 
      return lstCategorias_onChildClick(parent, v, groupPosition, childPosition, id); 
     } 
    }); 



    btnNewPlace = (Button)this.findViewById(R.act_gestao_categorias.novo_lugar); 
    btnNewBox = (Button)this.findViewById(R.act_gestao_categorias.nova_caixa); 

    btnNewPlace.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      btnNewPlace_onClick(v); 
     } 
    }); 

    btnNewBox.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      btnNewBox_onClick(v); 
     } 
    }); 

    registerForContextMenu(lstCategorias); 


    mPlacesCursor.registerContentObserver(new ObsPersonalArchive(handler)); 
    mBoxesCursor.registerContentObserver(new ObsPersonalArchive(handler)); 

} 


// Eventos da lista de locais e caixas 

public boolean lstCategorias_onGroupClick(ExpandableListView parent, View v, 
     int groupPosition, long id) { 
    return false; 
} 

public boolean lstCategorias_onChildClick(ExpandableListView parent, View v, 
     int groupPosition, int childPosition, long id) {   
    return false; 
} 

// Termina a actividade e volta à ActInicial, levando o local 

public void finish() { 
    // Prepare data intent 
    Intent data = new Intent(); 
    setResult(RESULT_OK, data); 
    data.putExtra("local", message); 
    // Activity finished ok, return the data 
    super.finish(); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    MenuInflater inflater = getMenuInflater(); 
    inflater.inflate(R.menu.act_start, menu); 
    return true; 
} 


// Eventos dos botões para criar novo local e caixa 

public void btnNewPlace_onClick(View view) { 
    Intent intent = new Intent(this, ActNewPlace.class); 
    startActivityForResult(intent, 1); 
} 

public void btnNewBox_onClick(View view) { 
    Intent intent = new Intent(this, ActNewBox.class); 
    startActivityForResult(intent, 2); 
} 

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     if (resultCode == RESULT_OK && requestCode == 1) { 
     if (data.hasExtra("novo_local") && data.hasExtra("nova_caixa")) { 

      // Chama o método para gravar o local na base de dados 
      Toast.makeText(this, "New place created!", Toast.LENGTH_LONG).show(); 
     } 
     } 
     if (resultCode == RESULT_OK && requestCode == 2) { 
     if (data.hasExtra("novo_local") && data.hasExtra("nova_caixa")) { 
      String novo_local = data.getExtras().getString("novo_local"); 
      String nova_caixa = data.getExtras().getString("nova_caixa"); 
      Toast.makeText(this, novo_local + nova_caixa, Toast.LENGTH_LONG).show(); 
     } 
     } 
    } 




public class ObsPersonalArchive extends ContentObserver { 

    public ObsPersonalArchive(Handler handler) { 
     super(handler);   
     } 
     @Override 
     public void onChange(boolean selfChange) { 
      super.onChange(selfChange); 
     }   
} 

}

邁克爾,新的I類寫道:

import android.app.Activity; 
import android.content.Intent; 
import android.database.ContentObserver; 
import android.database.Cursor; 
import android.database.DataSetObserver; 
import android.net.Uri; 
import android.os.Bundle; 
import android.os.Handler; 
import android.util.Log; 
import android.view.ContextMenu; 
import android.view.Menu; 
import android.view.MenuInflater; 
import android.view.MenuItem; 
import android.view.View; 
import android.view.ContextMenu.ContextMenuInfo; 
import android.widget.Button; 
import android.widget.ExpandableListAdapter; 
import android.widget.ExpandableListView; 
import android.widget.Toast; 
import android.support.v4.app.FragmentActivity; 
import android.support.v4.app.LoaderManager; 
import android.support.v4.content.CursorLoader; 
import android.support.v4.content.Loader; 
import android.support.v4.widget.CursorAdapter; 


public class ActPlacesManagement extends FragmentActivity 
implements LoaderManager.LoaderCallbacks<Cursor>{ 


private static final int DELETE_ID = Menu.FIRST; 

private static final String TAG = null; 


public Cursor mPlacesCursor; 
public Cursor mBoxesCursor; 
ExpandableListView lstCategorias; 
AdpPlacesManagement adapter; 
String message, message1, message2; 
String novo_local, nova_caixa; 
Button btnNewPlace, btnNewBox; 
Handler handler; 
LoaderManager loaderManager = getSupportLoaderManager(); 

private static final String[] PROJECTION_PLACES = new String[] { 
    ProvPersonalArchive.KEY_ROWID_PLACES, // 0 
    ProvPersonalArchive.KEY_DESIG_PLACES, // 1 
}; 

private static final String[] PROJECTION_BOXES = new String[] { 
    ProvPersonalArchive.KEY_ROWID_BOXES, // 0 
    ProvPersonalArchive.KEY_DESIG_BOXES, // 1 
    ProvPersonalArchive.KEY_PLACE_BOXES, // 2 
}; 

private static final int PLACES_LOADER = 1; 
private static final int BOXES_LOADER = 2; 


private LoaderManager.LoaderCallbacks<Cursor> mCallbacks; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 
    setContentView(R.layout.act_places_management);  

    mPlacesCursor = getContentResolver().query(ProvPersonalArchive.CONTENT_URI_PLACES, 
      PROJECTION_PLACES, null, null, null); 

    mBoxesCursor = getContentResolver().query(ProvPersonalArchive.CONTENT_URI_BOXES, 
      PROJECTION_BOXES, null, null, null); 


    // Lista de locais e caixas 

    lstCategorias = (ExpandableListView)this.findViewById(R.id.expandableGestaoCategorias); 

    adapter = new AdpPlacesManagement(this, mPlacesCursor, mBoxesCursor, this);  

    lstCategorias.setAdapter(adapter); 

    lstCategorias.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { 

     @Override 
     public boolean onGroupClick(ExpandableListView parent, View v, 
       int groupPosition, long id) { 
      return lstCategorias_onGroupClick(parent, v, groupPosition, id); 
     } 
    }); 

    lstCategorias.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { 

     @Override 
     public boolean onChildClick(ExpandableListView parent, View v, 
       int groupPosition, int childPosition, long id) { 
      return lstCategorias_onChildClick(parent, v, groupPosition, childPosition, id); 
     } 
    }); 


    // Botões para novo lugar e caixa 

    btnNewPlace = (Button)this.findViewById(R.act_gestao_categorias.novo_lugar); 
    btnNewBox = (Button)this.findViewById(R.act_gestao_categorias.nova_caixa); 

    btnNewPlace.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      btnNewPlace_onClick(v); 
     } 
    }); 

    btnNewBox.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      btnNewBox_onClick(v); 
     } 
    }); 

    registerForContextMenu(lstCategorias); 

    getSupportLoaderManager().initLoader(BOXES_LOADER, null, mCallbacks); 
    getSupportLoaderManager().initLoader(PLACES_LOADER, null, mCallbacks); 

} 


// Eventos da lista de locais e caixas 

public boolean lstCategorias_onGroupClick(ExpandableListView parent, View v, 
     int groupPosition, long id) { 
    return false; 
} 

public boolean lstCategorias_onChildClick(ExpandableListView parent, View v, 
     int groupPosition, int childPosition, long id) { 
    return false; 
} 


public void finish() { 
    Intent data = new Intent(); 
    setResult(RESULT_OK, data); 
    data.putExtra("local", message); 
    super.finish(); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    MenuInflater inflater = getMenuInflater(); 
    inflater.inflate(R.menu.act_start, menu); 
    return true; 
} 


// Eventos dos botões para criar novo local e caixa 

public void btnNewPlace_onClick(View view) { 
    Intent intent = new Intent(this, ActNewPlace.class); 
    startActivityForResult(intent, 1); 
} 

public void btnNewBox_onClick(View view) { 
    Intent intent = new Intent(this, ActNewBox.class); 
    startActivityForResult(intent, 2); 
} 

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     if (resultCode == RESULT_OK && requestCode == 1) { 
     if (data.hasExtra("novo_local") && data.hasExtra("nova_caixa")) { 
      Toast.makeText(this, "New place created!", Toast.LENGTH_LONG).show(); 
     } 
     } 
     if (resultCode == RESULT_OK && requestCode == 2) { 
     if (data.hasExtra("novo_local") && data.hasExtra("nova_caixa")) { 
      String novo_local = data.getExtras().getString("novo_local"); 
      String nova_caixa = data.getExtras().getString("nova_caixa"); 
      Toast.makeText(this, novo_local + nova_caixa, Toast.LENGTH_LONG).show(); 
     } 
     } 
    } 



// Menu de contexto 

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 
super.onCreateContextMenu(menu, v, menuInfo); 
ExpandableListView.ExpandableListContextMenuInfo info; 

try { 
    // Casts the incoming data object into the type for AdapterView objects. 
    info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo; 
} catch (ClassCastException e) { 
    // If the menu object can't be cast, logs an error. 
    Log.e(TAG, "bad menuInfo", e); 
    return; 
} 


int place = ExpandableListView.getPackedPositionGroup(info.packedPosition); 
int box = ExpandableListView.getPackedPositionChild(info.packedPosition); 
int tipo_clic = ExpandableListView.getPackedPositionType(info.packedPosition); 
String titulo = null; 

if (tipo_clic == ExpandableListView.PACKED_POSITION_TYPE_CHILD){ 
    titulo = (String) adapter.getChild(place, box); 
    menu.add(0, DELETE_ID, 0, R.string.delete_box); 
} 

if (tipo_clic == ExpandableListView.PACKED_POSITION_TYPE_GROUP){ 
    titulo = (String) adapter.getGroup(place); 
    menu.add(0, DELETE_ID, 0, R.string.delete_place); 
} 

if (titulo == null) { 
    // For some reason the requested item isn't available, do nothing 
    return; 
} 
menu.setHeaderTitle(titulo); 

} 


public boolean onContextItemSelected(MenuItem item) { 
ExpandableListView.ExpandableListContextMenuInfo info =  
(ExpandableListView.ExpandableListContextMenuInfo) item.getMenuInfo(); 
int tipo_clic = ExpandableListView.getPackedPositionType(info.packedPosition); 
switch(item.getItemId()) { 
case DELETE_ID: 
    if (tipo_clic == ExpandableListView.PACKED_POSITION_TYPE_CHILD){ 
     Toast.makeText(this, "The box was deleted", Toast.LENGTH_LONG).show(); 
    } 

    if (tipo_clic == ExpandableListView.PACKED_POSITION_TYPE_GROUP){ 
     Toast.makeText(this, "The place was deleted", Toast.LENGTH_LONG).show(); 
    } 
    return true; 
} 
return super.onContextItemSelected(item); 
} 


public Loader<Cursor> onCreateLoader(int id, Bundle arg1) { 

CursorLoader cursorLoader = new CursorLoader(getBaseContext()); 

if (id == BOXES_LOADER){ 
    cursorLoader = new CursorLoader(ActPlacesManagement.this, 
ProvPersonalArchive.CONTENT_URI_BOXES, PROJECTION_BOXES, null, null, null); 
}; 

if (id == PLACES_LOADER){ 
    cursorLoader = new CursorLoader(ActPlacesManagement.this, 
    ProvPersonalArchive.CONTENT_URI_PLACES, PROJECTION_PLACES, null, null, null); 
    }; 

return cursorLoader; 
} 



public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 

switch (loader.getId()) { 
case BOXES_LOADER: 
    mPlacesCursor = cursor; 
    break; 
case PLACES_LOADER: 
    mBoxesCursor = cursor; 
    break; 
} 

adapter = new AdpPlacesManagement(this, mPlacesCursor, mBoxesCursor, this);  

lstCategorias.setAdapter(adapter); 
} 



public void onLoaderReset(Loader<Cursor> loader) { 
switch (loader.getId()) { 
case BOXES_LOADER: 
    mPlacesCursor = null; 
    break; 
case PLACES_LOADER: 
    mBoxesCursor = null; 
    break; 
} 

adapter = new AdpPlacesManagement(this, mPlacesCursor, mBoxesCursor, this); 

} 

public class ObsPersonalArchive extends ContentObserver { 

    public ObsPersonalArchive(Handler handler) { 
     super(handler);   
     } 
     @Override 
     public void onChange(boolean selfChange) { 
      super.onChange(selfChange); 
     }   
} 
} 

而且錯誤

12-17 17:28:59.775:I/ActivityThread(16376 ):輸入進程活動msg = 101 12-17 17:28:59.795:I/ActivityThread(16376):退出進程活動msg = 101 12-17 17/28:59.805:I/ActivityThread(16376):輸入進程活動msg = 100 12-17 17:28:59.905:W/dalvikvm(16376):threadid = 1:線程退出時未捕獲的異常(group = 0x2aacc8a0) E/AndroidRuntime(16376):java.lang.RuntimeException:無法啓動活動ComponentInfo {0}無法啓動活動組件信息{ com.smartmobilelife.personal.archive/com.smartmobilelife.personal.archive.ActPlacesManagement}:java.lang.NullPointerException 12-17 17:28:59.915:E/AndroidRuntime(16376):at android.app.ActivityThread.performLaunchActivity E/AndroidRuntime(16376):at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2721) 12-17 17:28:59.915:E/AndroidRuntime(16376) AndroidRuntime(16376):在android.app.ActivityThread。訪問$ 2300(ActivityThread.java:132) 12-17 17:28:59.915:E/AndroidRuntime(16376):at android.app.ActivityThread $ H.handleMessage(ActivityThread.java:2071) 12-17 17:28 :59.915:E/AndroidRuntime(16376):at android.os.Handler.dispatchMessage(Handler.java:99) 12-17 17:28:59.915:E/AndroidRuntime(16376):at android.os.Looper.loop (Looper.java:123) 12-17 17:28:59.915:E/AndroidRuntime(16376):at android.app.ActivityThread.main(ActivityThread.java:4669) 12-17 17:28:59.915:E/AndroidRuntime(16376):at java.lang.reflect.Method.invokeNative(Native Method) 12-17 17:28:59.915:E/AndroidRuntime(16376):at java.lang.reflect.Method.invoke(Method。 java:521) 12-17 17:28:59.915:E/AndroidRuntime(16376):at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:876) 12-17 17:28:59.915:E/AndroidRuntime(16376):at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:634) 12-17 17:28:59.915:E/AndroidRuntime 16376):at dalvik.system.NativeStart.main(Native Method) 12-17 17:28:59.915:E/AndroidRuntime(16376):引起:java.lang.NullPointerException 12-17 17:28:59.915: E/AndroidRuntime(16376):在android.support.v4.app.LoaderManagerImpl.createLoader(LoaderManager.java:487) 12-17 17:28:59.915:E/AndroidRuntime(16376):在android.support.v4。 app.LoaderManagerImpl.createAndInstallLoader(LoaderManager.java:496) 12-17 17:28:59.915:E/AndroidRuntime(16376):at android.support.v4.app.LoaderManagerImpl.initLoader(LoaderManager.java:550) 12 -17 17:28:59.915:E/AndroidRuntime(16376):at com.smartmobilelife.personal.archive.ActPlacesManageme nt.onCreate(ActPlacesManagement.java:131) 12-17 17:28:59.915:E/AndroidRuntime(16376):at android.app.Instrumentation.callActivityOnCreate(Instrumentation。java:1047) 12-17 17:28:59.915:E/AndroidRuntime(16376):at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2669) 12-17 17:28:59.915:E/AndroidRuntime 16376):... 11更多

回答

0

我推薦使用CursorLoader,並且在接收更新時更新列表適配器上的光標。

默認情況下,CursorLoaders是ContentObservers,您只需確保ContentProvider在返回查詢光標時設置正確的uri,並且還要通知update/insert/delete中的更改。

CursorLoader文檔:http://developer.android.com/reference/android/content/CursorLoader.html

LoaderManager.LoaderCallbacks<Cursor> mLoaderCallback = new LoaderManager.LoaderCallbacks<Cursor>() { 

@Override 

public Loader<Cursor> onCreateLoader(int id, Bundle args) { 

    CursorLoader loader = new CursorLoader(context); 

    loader.setProjection(args.getStringArray("projection")); 

    loader.setSelection(args.getString("selection")); 

    loader.setSelectionArgs(args.getStringArray("selectionArgs")); 

    loader.setUri(Uri.parse(args.getString("uri"))); 



    return loader; 

} 



@Override 

public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) { 

    if (cursor == null) { 

     return; 

    } 



    YourListAdapter adapter = (YourListAdapter) getListAdapter(); 

    adapter.swapCursor(cursor); 

} 



@Override 

public void onLoaderReset(Loader<Cursor> cursorLoader) { 

    YourListAdapter adapter = (YourListAdapter) getListAdapter(); 

    adapter.swapCursor(null); 

} 

}; 



/* Calling a loader sample. */ 



Bundle loaderArgs = new Bundle(); 

loaderArgs.putString("uri", URI); 

loaderArgs.putStringArray("projection", PROJECTION); 



LoaderManager loaderManager = getLoaderManager(); 

loaderManager.initLoader(YOUR_LOADER_ID, loaderArgs, mYourLoaderCallback); 
+0

邁克爾,非常感謝你!但是我遇到了麻煩......我已經嘗試了裝載機,但無法使其工作。我在類ActPlacesManagement中粘貼了代碼,但OnCreateLoader中的上下文引用給出了錯誤(我將其更改爲getBaseContext)。使用getListAdapter(),Eclipse說方法getListAdapter()是未定義的類型new LoaderManager.LoaderCallbacks (){} ...主要問題是我不懂加載器的「邏輯」(並且已經讀取和讀取一堆教程)。再次感謝! –

+0

這純粹是一個讓你開始的樣本。如果你的加載器是你的片段或活動的成員,你可以使用那裏的上下文。 CursorLoaders與AsyncTasks類似,除非在這種情況下您不必擔心它的異步部分。當CursorLoader完成查詢時,它返回onLoaderFinished中的遊標。從這裏您可以使用光標將其與視圖關聯。 – novak

+0

謝謝Michael!我再次嘗試......如果你能花一點時間看看我在問題中寫到的新課程和日誌錯誤,只是給我一個提示,會很好。 –