Setting the items after creating ArrayAdapter? - android

In my app, I am showing a list of items downloaded from internet (of type pItem). I am using a custom ArrayAdapter that extends ArrayAdapter<pItem> which is basically like this:
public class PArrayAdapter extends ArrayAdapter<pItem> {
private List<pItem> pList = new ArrayList<pItem>();
public PArrayAdapter(Context context) {
super(context, R.layout.p_row);
this.context = context;
}
public void SetList(List<PItem> pl){
pList = pl;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = convertView;
if (rowView == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
rowView = vi.inflate(R.layout.p_row, null);
}
// ...
return rowView;
}
}
Now, normally when creating a custom ArrayAdapter, the list of items is set in the constructor. But in my case, as I dynamically fetch the items in an AsyncTask (the list is changing constantly), I separated the setting of the items with the creation of the adapter.
In my main activity, this is what I do: (only the main part of the code)
public class MainPageActivity extends SherlockFragmentActivity implements
OnScrollListener {
// List of items
private List<pItem> pList = new ArrayList<pItem>();
// Adapter
private arrayAdapter pAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_page);
//...
listView = (ListView) findViewById(R.id.p_list);
adpater = new PArrayAdapter(getApplicationContext());
new ASTask().execute("");
}
private class ASTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... args) {
// Add the downloaded items to list
pList.addAll(Downloader.GetItems());
return "";
}
#Override
protected void onPostExecute(String result) {
Log.d("Main", String.valueOf(pList.size())); // Shows the right number
// Show Items
pAdapter.setList(pList);
listView.setAdapter(pAdapter);
Handler mHandler = new Handler(Looper.getMainLooper());
Runnable rn = new Runnable() {
#Override
public void run() {
pAdapter.notifyDataSetChanged();
}
};
mHandler.post(rn);
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
}
Here is the problem: When I run it, nothing is shown in the listView. It doesn't give any errors.
But if I set the list in the constructor of PArrayAdapter, everything works fine and I see the items.
What am I doing wrong here?

in onPostExecute
remove this code
Handler mHandler = new Handler(Looper.getMainLooper());
Runnable rn = new Runnable() {
#Override
public void run() {
pAdapter.notifyDataSetChanged();
}
};
mHandler.post(rn);
add this line only
pAdapter.notifyDataSetChanged();

Add
pAdapter.notifyDataSetChanged();
at the end of onPostExecute() method.
Try like this:
#Override
protected void onPostExecute(String result) {
Log.d("Main", String.valueOf(pList.size())); // Shows the right number
// Show Items
pAdapter.setList(pList);
listView.setAdapter(pAdapter);
pAdapter.notifyDataSetChanged();
}

OK. I found what was my problem. It was actually a rookie mistake:
Instead of assigning the input list to the list inside adapter:
pList = pl;
I should have add all the items like this:
pList.addAll(pl);
This solved the problem.

Related

Combine Activity and fragment into a class android

I want to ask,
I have 2 classes:
1. an activity class (to get data from json)
2. a fragment class (not to do something)
and I want to get data from json of activity via fragment class.
Can be combine Activity and Fragment in a class ? and how to do ?
I combined activity and fragment in a Fragment class, I have used a GridView to get data and display
JSON, execute the AsyncTask in the this Fragment
This is my code after updated 25/10:
public class FeedBackFragment extends Fragment {
ProgressDialog pDialog;
JSONParser jsonParser = new JSONParser();
MyAdapter adapter;
JSONArray manufacturers = null;
// manufacturers JSON url
private static final String URL_MANUFACTURERS ="MYURL";
public FeedBackFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.feedback_gridview_manufacturer, container, false);
GridView gridView = (GridView) view.findViewById(R.id.gridview);
gridView.setAdapter(new MyAdapter(getActivity(), manufacturersList));
gridView.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View view, int arg2, long arg3) {
// on selecting a single manufacturer
// CategoryCarActivity will be launched to show category car inside the manufacturer
Intent i = new Intent(getActivity(), CategoryCarActivity.class);
// send manufacturer id to activity to get list of cars under that manufacturer
String manufacturer_id = ((TextView) view.findViewById(R.id.manufacturer_id)).getText().toString();
i.putExtra("manufacturer_id", manufacturer_id);
startActivity(i);
}
});
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
// manufacturersList = new ArrayList<>();
new LoadAllManufacturers().execute();
}
class LoadAllManufacturers extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(getActivity());
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
/**
* After completing background task Dismiss the progress dialog
* **/
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
adapter.notifyDataSetChanged();
// dismiss the dialog after getting all manufacturers
if (pDialog.isShowing())
pDialog.dismiss();
}
}
private class MyAdapter extends BaseAdapter
{
// List<POJOManufacturer> listData = null;
LayoutInflater inflater;
Context context;
public MyAdapter(Context context, ArrayList<HashMap<String, String>> arrayList)
{
// this.context = context;
this.manufacturersList = arrayList;
inflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
if (manufacturersList != null)
return manufacturersList.size();
return 0;
}
#Override
public Object getItem(int i)
{
if (manufacturersList != null)
return manufacturersList.get(i);
return null;
}
#Override
public long getItemId(int i)
{
if (manufacturersList != null)
return manufacturersList.get(i).hashCode();
return 0;
}
#Override
public View getView(int i, View convertView, ViewGroup viewGroup)
{
ViewHolder holder;
if (convertView == null)
{
convertView = inflater.inflate(R.layout.gridview_item, null);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.text);
holder.iconName = (ImageView) convertView.findViewById(R.id.picture);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.name.setText(this.manufacturersList.get(i).getClass().getName());
// holder.iconName.setImageResource(this.manufacturersList.get(i).image);
return convertView;
}
public class ViewHolder
{
TextView name;
ImageView iconName;
}
}
}
I have updated and added: manufacturerList = new ArrayList<>. everything seem is better, and it happen some issues in getView() method,
I have try and it's only display with 7 empty items in gridview, and not display content and image
So How fill data from Adapter into Gridview?
constructor ManufacturerFragment in class ManufacturerFragment cannot be applied to given types;
gridView.setAdapter() takes an adapter, not a Fragment
And new ManufacturerFragment() doesn't accept an Context.
I am not really sure why you think you need to create a new ManufacturerFragment within the Fragment class you already are in. Did you mean to do gridView.setAdapter(new MyAdapter(getActivity()))?
Also, your manufacturersList needs to be loaded into that adapter, so you'll need to figure that out.
And you need to use getActivity() instead of getActivity().getApplicationContext() in most places.
Then, you should only call new LoadAllManufacturers().execute(); in either onCreateView or onActivityCreated, not both. Otherwise, you're running two AsyncTasks.
Then, onPostExecute already runs on the UI thread, no need to use getActivity().runOnUiThread(new Runnable() {...
Once you do figure out how to put that ArrayList into the Adapter class, you'll want to call adapter.notifyDataSetChanged() within onPostExecute to tell the adapter to refresh the data, thereby updating the GridView to display the data.

Why is my ListActivity stuck on the /empty element?

I'm trying to use a ListActivity on my Android App but it isn't working the way it should.
Here is my Activity :
public class MainActivity extends ListActivity {
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_terminals_list); //The special layout
TerminalsArrayAdapter adapter = new TerminalsArrayAdapter(this); // A custom adapter
setListAdapter(adapter);
RequestTask task = new RequestTask(adapter); // An Async task
task.execute("/terminals/all");
}
}
Here is my layout :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
<TextView
android:id="#android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Loading..." />
</LinearLayout>
Here is my custom adapter :
public class TerminalsArrayAdapter extends ArrayAdapter<String[]> {
private Activity mContext;
private ArrayList<String[]> mObjects = new ArrayList<String[]>();
public TerminalsArrayAdapter(Activity context) {
super(context, R.layout.terminals_listview_item);
this.mContext = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View elementView;
if(convertView==null){
LayoutInflater inflater = mContext.getLayoutInflater();
elementView = inflater.inflate(R.layout.terminals_listview_item, parent);
...
// Some things with my view
} else {
elementView = convertView;
}
...
// Some things with my view
return elementView;
}
public void updateTerminals(ArrayList<String[]> newObject){
mObjects.clear();
mObjects.addAll(newObject);
notifyDataSetChanged();
Log.d("TerminalsArrayAdapter", "Dataset Changed !");
}
}
And here is my Async task :
public class RequestTask extends AsyncTask<String, Void, ArrayList<String[]>>{
private final TerminalsArrayAdapter mAdapter;
public RequestTask(TerminalsArrayAdapter adapter) {
mAdapter = adapter;
}
#Override
protected ArrayList<String[]> doInBackground(String... params) {
...
// retrieve some data from my server
return response;
}
#Override
protected void onPostExecute(ArrayList<String[]> response) {
Log.d("response_server","GOT IT !");
mAdapter.updateTerminals(response);
}
}
As I understood, the ListView will be shown only if the adapter is not empty. If it is empty, it will be the TextView which will be displayed.
This is the way my app should work :
The app creates an empty adapter. This will display the "Loading..." TextView
The app creates a new Async task which will retrieve some needed data from my server
When the Async task finishes, it will call the .updateTerminals() method
This method will update the entries of the custom adapter and call notifyDataSetChanged()
The app should now display the ListView with the freshly retrieved data
The steps 1 to 4 are working fine. The problem occurs on step 5 : Even if the data has been updated, my app doesn't refresh the screen to show me the ListView and stays on the "Loading..." TextView.
I tried to figure out what was wrong with my code, but I wasn't able to. I'd love to hear your suggestions/solutions ! Thanks !
PS: Tell me if you need any thing to understand my issue better.
Your ListView height should be match_parent.
Try to play around with setVisibility(View.GONE) and setVisibility(View.VISIBLE) to:
show TextView & hide ListView
show ListView & hide TextView
public class MainActivity extends ListActivity {
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_terminals_list); //The special layout
// create your list with specific method to be able call her many time
// prefer to create then refresh with new data
CreateList(Passanydata);
RequestTask task = new RequestTask(adapter); // An Async task
task.execute("/terminals/all");
}
}
public void CreateList(ArrayList<String[]> response){
TerminalsArrayAdapter adapter = new TerminalsArrayAdapter(this,response); // A custom adapter
setListAdapter(adapter);
}
#Override
protected void onPostExecute(ArrayList<String[]> response) {
Log.d("response_server","GOT IT !");
// after you got your new data , pass it to your list
CreateList(response);
}
public class TerminalsArrayAdapter extends ArrayAdapter<String[]> {
private Activity mContext;
private ArrayList<String[]> mObjects = new ArrayList<String[]>();
public TerminalsArrayAdapter(Activity context,ArrayList<String[]> objects) {
super(context, R.layout.terminals_listview_item);
this.mContext = context;
// when you have your data it will be able to use it here
this.mObjects = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View elementView;
if(convertView==null){
LayoutInflater inflater = mContext.getLayoutInflater();
elementView = inflater.inflate(R.layout.terminals_listview_item, parent);
...
// Some things with my view
} else {
elementView = convertView;
}
...
// Some things with my view
return elementView;
}
}

Android Synchronization with AsyncTask

This is my main activity:
adapter.setNotifyOnChange(true);
lv = (ListView) findViewById(R.id.listView1);
lv.setAdapter(adapter);
public void onClick(View view) {
adapter.add(text);
new DoSomethingWithListViewChild(lv, index).execute();
}
And this is the AsyncTask DoSomethingWithListViewChild:
public class DoSomethingWithListViewChild extends AsyncTask<Void, Void, Void> {
TextView tv;
public DoSomethingWithListViewChild (ListView lv, int index) {
View v = lv.getChildAt(index - lv.getFirstVisiblePosition());
tv = (TextView) v.findViewById(R.id.textTitle);
}
#Override
protected Void doInBackground(Void... params) {
// Do something with TV
return null;
}
The problem is that lv is still empty when the code View v = lv.getChildAt(index - lv.getFirstVisiblePosition()); is being executed.
I tried some synchronization with lock objects but I'm ending with deadlocks or other errors.
How do I wait untill lv is not empty?
Edit:
Ok, I tried this:
...
ConditionVariable lock = new ConditionVariable(false);
...
public void onClick(View view) {
adapter.add(text);
lock.block();
new DoSomethingWithListViewChild(lv, index).execute();
}
And in my custom adapter:
public class MyAdapter extends ArrayAdapter<SpannableString> {
ConditionVariable lock;
public MyAdapter(Context context, int layout_resource_id, ConditionVariable lock) {
...
this.lock = lock;
...
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
...
lock.open();
return convertView;
}
}
But the programm just hangs. I need to find the exact moment when lv is populated to open the lock. It clearly not in the getView method.. It even don't reach the lock.open();
May be needs to call adapter.notifyDayaSetChanged() after adapter.add(text)

Android ListView not refreshing after notifyDataSetChanged

My ListFragment code
public class ItemFragment extends ListFragment {
private DatabaseHandler dbHelper;
private static final String TITLE = "Items";
private static final String LOG_TAG = "debugger";
private ItemAdapter adapter;
private List<Item> items;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.item_fragment_list, container, false);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.setHasOptionsMenu(true);
super.onCreate(savedInstanceState);
getActivity().setTitle(TITLE);
dbHelper = new DatabaseHandler(getActivity());
items = dbHelper.getItems();
adapter = new ItemAdapter(getActivity().getApplicationContext(), items);
this.setListAdapter(adapter);
}
#Override
public void onResume() {
super.onResume();
items.clear();
items = dbHelper.getItems(); //reload the items from database
adapter.notifyDataSetChanged();
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
if(dbHelper != null) { //item is edited
Item item = (Item) this.getListAdapter().getItem(position);
Intent intent = new Intent(getActivity(), AddItemActivity.class);
intent.putExtra(IntentConstants.ITEM, item);
startActivity(intent);
}
}
}
My ListView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
But this does not refresh the ListView. Even after restarting app the updated items are not shown. My ItemAdapter extends BaseAdapter
public class ItemAdapter extends BaseAdapter{
private LayoutInflater inflater;
private List<Item> items;
private Context context;
public ProjectListItemAdapter(Context context, List<Item> items) {
super();
inflater = LayoutInflater.from(context);
this.context = context;
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
#Override
public Object getItem(int position) {
return items.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ItemViewHolder holder = null;
if(convertView == null) {
holder = new ItemViewHolder();
convertView = inflater.inflate(R.layout.list_item, parent,false);
holder.itemName = (TextView) convertView.findViewById(R.id.topText);
holder.itemLocation = (TextView) convertView.findViewById(R.id.bottomText);
convertView.setTag(holder);
} else {
holder = (ItemViewHolder) convertView.getTag();
}
holder.itemName.setText("Name: " + items.get(position).getName());
holder.itemLocation.setText("Location: " + items.get(position).getLocation());
if(position % 2 == 0) {
convertView.setBackgroundColor(context.getResources().getColor(R.color.evenRowColor));
} else {
convertView.setBackgroundColor(context.getResources().getColor(R.color.oddRowColor));
}
return convertView;
}
private static class ItemViewHolder {
TextView itemName;
TextView itemLocation;
}
}
Can someone help please?
Look at your onResume method in ItemFragment:
#Override
public void onResume() {
super.onResume();
items.clear();
items = dbHelper.getItems(); // reload the items from database
adapter.notifyDataSetChanged();
}
what you just have updated before calling notifyDataSetChanged() is not the adapter's field private List<Item> items; but the identically declared field of the fragment. The adapter still stores a reference to list of items you passed when you created the adapter (e.g. in fragment's onCreate).
The shortest (in sense of number of changes) but not elegant way to make your code behave as you expect is simply to replace the line:
items = dbHelper.getItems(); // reload the items from database
with
items.addAll(dbHelper.getItems()); // reload the items from database
A more elegant solution:
1) remove items private List<Item> items; from ItemFragment - we need to keep reference to them only in adapter
2) change onCreate to :
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setHasOptionsMenu(true);
getActivity().setTitle(TITLE);
dbHelper = new DatabaseHandler(getActivity());
adapter = new ItemAdapter(getActivity(), dbHelper.getItems());
setListAdapter(adapter);
}
3) add method in ItemAdapter:
public void swapItems(List<Item> items) {
this.items = items;
notifyDataSetChanged();
}
4) change your onResume to:
#Override
public void onResume() {
super.onResume();
adapter.swapItems(dbHelper.getItems());
}
You are assigning reloaded items to global variable items in onResume(), but this will not reflect in ItemAdapter class, because it has its own instance variable called 'items'.
For refreshing ListView, add a refresh() in ItemAdapter class which accepts list data i.e items
class ItemAdapter
{
.....
public void refresh(List<Item> items)
{
this.items = items;
notifyDataSetChanged();
}
}
update onResume() with following code
#Override
public void onResume()
{
super.onResume();
items.clear();
items = dbHelper.getItems(); //reload the items from database
**adapter.refresh(items);**
}
In onResume() change this line
items = dbHelper.getItems(); //reload the items from database
to
items.addAll(dbHelper.getItems()); //reload the items from database
The problem is that you're never telling your adapter about the new items list. If you don't want to pass a new list to your adapter (as it seems you don't), then just use items.addAll after your clear(). This will ensure you are modifying the same list that the adapter has a reference to.
If the adapter is already set, setting it again will not refresh the listview. Instead first check if the listview has a adapter and then call the appropriate method.
I think its not a very good idea to create a new instance of the adapter while setting the list view. Instead, create an object.
BuildingAdapter adapter = new BuildingAdapter(context);
if(getListView().getAdapter() == null){ //Adapter not set yet.
setListAdapter(adapter);
}
else{ //Already has an adapter
adapter.notifyDataSetChanged();
}
Also you might try to run the refresh list on UI Thread:
activity.runOnUiThread(new Runnable() {
public void run() {
//do your modifications here
// for example
adapter.add(new Object());
adapter.notifyDataSetChanged()
}
});
If you want to update your listview doesn't matter if you want to do that on onResume(), onCreate() or in some other function, first thing that you have to realize is that you won't need to create a new instance of the adapter, just populate the arrays with your data again.
The idea is something similar to this :
private ArrayList<String> titles;
private MyListAdapter adapter;
private ListView myListView;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
myListView = (ListView) findViewById(R.id.my_list);
titles = new ArrayList<String>()
for(int i =0; i<20;i++){
titles.add("Title "+i);
}
adapter = new MyListAdapter(this, titles);
myListView.setAdapter(adapter);
}
#Override
public void onResume(){
super.onResume();
// first clear the items and populate the new items
titles.clear();
for(int i =0; i<20;i++){
titles.add("New Title "+i);
}
adapter.notifySetDataChanged();
}
So depending on that answer you should use the same List<Item> in your Fragment. In your first adapter initialization you fill your list with the items and set adapter to your listview. After that in every change in your items you have to clear the values from the main List<Item> items and than populate it again with your new items and call notifySetDataChanged();.
That's how it works : ).
An answer from AlexGo did the trick for me:
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
messages.add(m);
adapter.notifyDataSetChanged();
getListView().setSelection(messages.size()-1);
}
});
List Update worked for me before when the update was triggered from a GUI event, thus being in the UI thread.
However, when I update the list from another event/thread - i.e. a call from outside the app, the update would not be in the UI thread and it ignored the call to getListView. Calling the update with runOnUiThread as above did the trick for me. Thanks!!
Try this
#Override
public void onResume() {
super.onResume();
items.clear();
items = dbHelper.getItems(); //reload the items from database
adapter = new ItemAdapter(getActivity(), items);//reload the items from database
adapter.notifyDataSetChanged();
}
adpter.notifyDataSetInvalidated();
Try this in onPause() method of Activity class.
If your list is contained in the Adapter itself, calling the function that updates the list should also call notifyDataSetChanged().
Running this function from the UI Thread did the trick for me:
The refresh() function inside the Adapter
public void refresh(){
//manipulate list
notifyDataSetChanged();
}
Then in turn run this function from the UI Thread
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
adapter.refresh()
}
});
Try like this:
this.notifyDataSetChanged();
instead of:
adapter.notifyDataSetChanged();
You have to notifyDataSetChanged() to the ListView not to the adapter class.
adapter.setNotifyDataChanged()
should do the trick.

Android listview item doesn't appear

I should write in the title instead of 'doesn't work' something like 'I
don't know how to do it' but the first version feels better :).
What I am trying to do is the following:
Download the xml from the web, parse it and create ArrayList of some
objects (done and working)
Display the objects using custom Adapter (doesn't work)
The second one works if I add the items to my ArrayList before I add it to
the view using
m_orderAdapter = new OrderAdapter(this,m_orders); //code for orderadapter
below
setListAdapter(m_orderAdapter);
I have found on the web something like this: (in my onCreate method)
handler = new Handler();
viewOrders = new Runnable(){
#Override
public void run() {
getOrders();
}
};
new Thread(){
#Override
public void run(){
handler.post(viewOrders);
}
}.start();
then, the following code for the methods:
private void getOrders(){
try{
OrderManager om = new OrderManager();
m_orders = om.getOrdersFromWeb();
Log.i("ARRAY", ""+ m_orders.size());
} catch (Exception e) {
Log.e("BACKGROUND_PROC", e.getMessage());
}
runOnUiThread(returnRes);
}
OrderManager downloads and parse the xml into Order objects and returns
array list of those. Then I set this list to my member array list m_orders.
Once downloading and parsing is done I run returnRes method on the ui thread
using runOnUiThread method
private Runnable returnRes = new Runnable() {
#Override
public void run() {
if(m_orders != null && m_orders.size() > 0){
Log.i("ORDER",m_orders.get(0).getOrder_id());
setListAdapter(m_orderAdapter);
m_orderAdapter.notifyDataSetChanged();
}
m_orderAdapter.notifyDataSetChanged();
}
};
and I call notifyDataSetChanged() on my adapter.
The view I do all this stuff extends ListView and the code for the adapter
itself is listed below:
public class OrderAdapter extends BaseAdapter{
private Context ctx;
private List<Order> orders;
public OrderAdapter(Context ctx, List<Order> orderLst){
this.ctx = ctx;
this.orders = orderLst;
}
#Override
public int getCount() {
return orders.size();
}
#Override
public Object getItem(int pos) {
return orders.get(pos);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Order o = orders.get(position);
return new OrderListAdapterView(this.ctx,o);
}
}
When I debug I have the data inside my m_orders list but when I call
notifyDataSetChanged nothing happens, I've read that I have to execute that
on the UI thread which I think I do. So whats the problem ?
any help highly appreciated, or maybe just a link to the nice tutorial on
the web explaining this issue on how to update the list view at runtime ?
Hey Arutha - why don't you see my answer for this post - I think it is what you need.
Or just let me repost it here
You can extend ArrayAdapter. Here's code example for you. In this example - SearchItem is some custom POJO. Basically you need to override getView() method to build your row by inflating row layout and then populating values based on List of items and current position
class SearchItemsAdapter extends ArrayAdapter<SearchItem> {
Activity context;
List<SearchItem> items;
SearchHeader header;
#SuppressWarnings("unchecked")
public SearchItemsAdapter(final Activity context,
final Map<SearchHeader, List<SearchItem>> result) {
super(context, R.layout.item, (List) ((Object[]) result.values()
.toArray())[0]);
this.context = context;
this.header = result.keySet().iterator().next();
this.items = result.get(this.header);
}
#Override
public View getView(final int position, final View convertView,
final ViewGroup parent) {
final View view = this.context.getLayoutInflater().inflate(
R.layout.item, null);
final SearchItem item = this.items.get(position);
((TextView) view.findViewById(R.id.jt)).setText(item.jt);
((TextView) view.findViewById(R.id.dp)).setText(item.dp);
((TextView) view.findViewById(R.id.cn)).setText(item.cn);
((TextView) view.findViewById(R.id.loc)).setText(item.loc.name);
final TextView body = ((TextView) view.findViewById(R.id.e));
body.setText(item.e);
body.setTag(item.src[0]);
((TextView) view.findViewById(R.id.src)).setText(item.src[1]);
return view;
}
}

Categories

Resources