Reputation: 18639
I am setting up a ListView adapter like this:
public class SeeAllQuestionsActivity extends Activity
{
//ArrayAdapter<Question> adapter;
SimpleAdapter mSchedule = null;
ListView list = new ListView (this);
TextView loading_questions = null;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.all_question_page);
TextView loading_questions = (TextView) findViewById(R.id.loading_questions);
list = (ListView) findViewById(R.id.list);
ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
HashMap<String, String> map = new HashMap<String, String>();
mSchedule = new SimpleAdapter(this, mylist, R.layout.questions_list,
new String[] {"train", "from", "to"},
new int[] {R.id.TRAIN_CELL, R.id.FROM_CELL, R.id.TO_CELL});
list.setAdapter(mSchedule);
list.setTextFilterEnabled(true);
list.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View view,
int position, long id)
{
...
and then making a remote Asynch call to get the list from my database, and trying to do this in the onPostExecute method:
ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
HashMap<String, String> map = new HashMap<String, String>();
try
{
JSONArray obj = new JSONArray(result);
if ( obj != null )
{
for ( int i = 0; i < obj.length(); i++ )
{
JSONObject o = obj.getJSONObject(i);
map.put("train", "Business Name");
map.put("from", ">");
map.put("to", ">");
mylist.add(map);
map = new HashMap<String, String>();
map.put("train", "103(x)");
map.put("from", "6:35 AM");
map.put("to", "7:45 AM");
mylist.add(map);
}
}
}
catch ( Exception e )
{
}
list.setAdapter(mSchedule);
but I get a Null Pointer exception on this line:
ListView list = new ListView (this);
But I think generally I am way off in how this needs to be done in the postExecute method. Any help with how to do this correctly is much appreciated.
Upvotes: 2
Views: 422
Reputation: 7892
In your OnCreate you define a new SimpleAdapter and attach it to your ListView. This is correct. The datasource (mylist
in your case) is empty at this point so you will fill it with in an AsyncTask
.
In your onPostExecute you are creating a new ArrayList
. Depending on the result you receive, you fill it. After you did this, you are setting the adapter again. Which will do nothing because the adapter has no data.. What you want to do, is give your new filled list to your Adapter so it can fill the ListView
with your data.
Solution 1
onPostExecute {
// create a list to store your data
new ArrayList
// fill the new list with the data you received (result)
fillArrayList from JSON
// create an adapter and give the new list with it
mAdapter = new SimpleAdapter(.., ArrayList, ...)
listView.setAdapter(mAdapter);
}
This is one way you can do it and fits you current implementation.
Solution 2
I would opt for this solution
onPostExecute {
// don't create a new arraylist but use the mylist-object you created in the OnCreate
fill mylist object with new data
// mylist is the datasource of your adapter and it is now changed.
// let the ListView know his adapter received new information
mSchedule.notifyDataSetChanged
}
UPDATE
Check out this tutorial. I use the same layouts and same source to fill my list but I have altered it so it is similar to your case. Good luck :)
MainActivity
public class MainActivity extends Activity {
private List<HashMap<String, String>> fillMaps;
private SimpleAdapter adapter;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView lv = (ListView) findViewById(R.id.listview);
String[] from = new String[] { "rowid", "col_1", "col_2", "col_3" };
int[] to = new int[] { R.id.item1, R.id.item2, R.id.item3, R.id.item4 };
// My data
fillMaps = new ArrayList<HashMap<String, String>>();
// Create an adapter which will tell my ListView what to show..
// fillMaps is still empty so at the moment it my ListView will show
// nothing.
adapter = new SimpleAdapter(this, fillMaps, R.layout.row, from, to);
lv.setAdapter(adapter);
// Retreive data from somewhere
new UpdateListWithAsyncTask().execute();
}
private class UpdateListWithAsyncTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
// do stuff
return null;
}
protected void onPostExecute(Void result) {
// Fill your datasource that your adapter has. In my case fillMaps
for (int i = 0; i < 10; i++) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("rowid", "" + i);
map.put("col_1", "col_1_item_" + i);
map.put("col_2", "col_2_item_" + i);
map.put("col_3", "col_3_item_" + i);
fillMaps.add(map);
}
// my datasource is now changed, I want my adapter to know this and
// update my ListView
adapter.notifyDataSetChanged();
}
}
}
Upvotes: 1
Reputation: 1230
As i remember and as a logical conclusion: In the moment of your call the reference of this is null. this will be accessed in the constructor of your ListView thus a NullPointerException will be raised. If you want to create it dynamically you have to call the ListView constructor within the onCreate method of your Activity.
At least it's better to implement it as suggested by MartijnVanMierloo, if possible.
Upvotes: 1