Note that there are some explanatory texts on larger screens.

plurals
  1. PORefresh expandable list using a content observer (Android)
    text
    copied!<p>I have an expandable list, with a custom adapter, two cursor (from base expandable list adapter), and a content provider.</p> <p>Now, my main objective is to refresh this expandable list, after inserting new data with a activity that is called with a intent. I'm trying a Content Observer, but with no success, because no refresh is done.</p> <p>I put the relevant code (I think). Thank you very much.</p> <pre><code>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 &amp;&amp; requestCode == 1) { if (data.hasExtra("novo_local") &amp;&amp; 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 &amp;&amp; requestCode == 2) { if (data.hasExtra("novo_local") &amp;&amp; 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); } } </code></pre> <p>}</p> <p>Michael, the new class I wrote:</p> <pre><code>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&lt;Cursor&gt;{ 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&lt;Cursor&gt; 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 &amp;&amp; requestCode == 1) { if (data.hasExtra("novo_local") &amp;&amp; data.hasExtra("nova_caixa")) { Toast.makeText(this, "New place created!", Toast.LENGTH_LONG).show(); } } if (resultCode == RESULT_OK &amp;&amp; requestCode == 2) { if (data.hasExtra("novo_local") &amp;&amp; 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&lt;Cursor&gt; 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&lt;Cursor&gt; 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&lt;Cursor&gt; 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); } } } </code></pre> <p>And the errors</p> <blockquote> <p>12-17 17:28:59.775: I/ActivityThread(16376): enter process activity msg = 101 12-17 17:28:59.795: I/ActivityThread(16376): exit process activity msg = 101 12-17 17:28:59.805: I/ActivityThread(16376): enter process activity msg = 100 12-17 17:28:59.905: W/dalvikvm(16376): threadid=1: thread exiting with uncaught exception (group=0x2aacc8a0) 12-17 17:28:59.915: E/AndroidRuntime(16376): FATAL EXCEPTION: main 12-17 17:28:59.915: E/AndroidRuntime(16376): java.lang.RuntimeException: Unable to start activity ComponentInfo{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(ActivityThread.java:2705) 12-17 17:28:59.915: E/AndroidRuntime(16376): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2721) 12-17 17:28:59.915: E/AndroidRuntime(16376): at android.app.ActivityThread.access$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): Caused by: java.lang.NullPointerException 12-17 17:28:59.915: E/AndroidRuntime(16376): at android.support.v4.app.LoaderManagerImpl.createLoader(LoaderManager.java:487) 12-17 17:28:59.915: E/AndroidRuntime(16376): at 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.ActPlacesManagement.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 more</p> </blockquote>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload