Android RecyclerView not populating using Volley [duplicate] - java

Here is the code of the fragment in which I am setting a custom adapter to the list.
There no errors but the ListView is empty. I have implemented getCount() which returns right number of items in my ArrayList. I don't see ("Inside", "GetView") in the logcat
Fragment
public class ServiceCarListFragment extends Fragment {
private String url;
private ArrayList<CarDetail> carDetailList = new ArrayList<CarDetail>();
private CarListAdapter adapter;
private ListView mList;
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
url = getActivity().getIntent().getStringExtra("url");
new DownloadCarDetail().execute(url);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View v = inflater.inflate(R.layout.fragment_service_car_list, container, false);
mList = (ListView) v.findViewById(R.id.list);
mList.setAdapter(adapter);
for (CarDetail car : carDetailList) {
// START LOADING IMAGES FOR EACH STUDENT
car.loadImage(adapter);
}
return v;
}
class DownloadCarDetail extends AsyncTask<String, String, ArrayList<CarDetail>> {
#Override
protected ArrayList<CarDetail> doInBackground(String... params) {
// TODO Auto-generated method stub
ArrayList<CarDetail> carDetailList = JsonParser.parseJson(params[0]);
return carDetailList;
}
#Override
protected void onPostExecute(ArrayList<CarDetail> carDetailList) {
// TODO Auto-generated method stub
ServiceCarListFragment.this.carDetailList = carDetailList;
Log.d("dccs", String.valueOf(ServiceCarListFragment.this.carDetailList.size()));
adapter = new CarListAdapter(getActivity(), ServiceCarListFragment.this.carDetailList);
Log.d("dccs", String.valueOf((adapter.getCount())));
}
}
}
CustomAdapter
public class CarListAdapter extends BaseAdapter {
private ArrayList<CarDetail> items = new ArrayList<CarDetail>();
private Context context;
public CarListAdapter(Context context, ArrayList<CarDetail> items) {
this.context = context;
this.items = items;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return items.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Log.d("Inside", "GetView");
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
ViewHolder holder = null;
CarDetail car = items.get(position);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.car_list_row, null);
holder = new ViewHolder();
holder.tvCarName = (TextView) convertView.findViewById(R.id.tvCarName);
holder.tvDailyPriceValue = (TextView) convertView.findViewById(R.id.tvWeeklyPriceValue);
holder.tvWeeklyPriceValue = (TextView) convertView.findViewById(R.id.tvWeeklyPriceValue);
holder.imgCar = (ImageView) convertView.findViewById(R.id.imgCar);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tvCarName.setText(car.getCarName());
if (car.getImage() != null) {
holder.imgCar.setImageBitmap(car.getImage());
} else {
// MY DEFAULT IMAGE
holder.imgCar.setImageResource(R.drawable.ic_action_call);
}
return convertView;
}
static class ViewHolder {
TextView tvCarName;
TextView tvDailyPriceValue;
TextView tvWeeklyPriceValue;
ImageView imgCar;
}
}

The only reasons getView is not called are:
getCount returns 0.
you forget to call setAdapter on the ListView.
If the ListView's visibility (or its container's visibility) is GONE. Thanks to #TaynãBonaldo for the valuable input.
ListView is not attached to any viewport layout. That is, mListView = new ListView(...) is used without myLayout.addView(mListView).
In the onPostExcute, after you create a new instance of CarListAdapter I will suggest you to update the new instance to your ListView. Indeed you need to call again
mList.setAdapter(adapter);
Edit: setAdapter should be always called on the ui thread, to avoid unexpected behaviours
Edit2:
The same applies to RecyclerView. Make sure that
getItemCount is returning a value grater than 0 (usually the dataset size)
both setLayoutManager and setAdapter have to be called on the UI Thread
The visibility of the widget has to be set to VISIBLE

you must verify that the list has elements might have an error when adding items to your list .
To verify , use the method:
adapter.getCount();

I faced similar problem. Here is a simple work around to solve it:
In your onCreateView, you will have to wait before the view gets created. So change your lines from this:
mList = (ListView)v.findViewById(R.id.list);
mList.setAdapter(adapter);
CHANGE THE ABOVE TWO LINES INTO:
mList = (ListView)v.findViewById(R.id.list);
mList.post(new Runnable() {
public void run() {
mList.setAdapter(adapter);
}
});
Hope this will help others who would run into similar problem

You are missing the super class in the constructor. See my example below:
public AppDataAdapter(Activity a, int textViewResourceId, ArrayList<AppData> entries) {
super(a, textViewResourceId, entries);
this.entries = entries;
this.activity = a;
}

What you have been doing is
In your adapter
public CarListAdapter(Context context , ArrayList<CarDetail> items) {
this.context = context;
this.items = items;
}
in your Fragment
adapter = new CarListAdapter(getActivity(),ServiceCarListFragment.this.carDetailList);
I hope you will be using FragmentActivity
You need to call
adapter = new CarListAdapter(YOUR_ACTIVITY_CONTEXT, carDetailList);
where YOUR_ACTIVITY_CONTEXT will be your FragmentActivity

I had the same problem. And after trying all tips above my getView was still not being called. So I tried to remove the ScrollView that I used outside the ListView. Then the getView worked well. Just for add one more posibility. I Hope help someone.

Related

Array Adapter's "getView()" doesn't get called [duplicate]

Here is the code of the fragment in which I am setting a custom adapter to the list.
There no errors but the ListView is empty. I have implemented getCount() which returns right number of items in my ArrayList. I don't see ("Inside", "GetView") in the logcat
Fragment
public class ServiceCarListFragment extends Fragment {
private String url;
private ArrayList<CarDetail> carDetailList = new ArrayList<CarDetail>();
private CarListAdapter adapter;
private ListView mList;
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
url = getActivity().getIntent().getStringExtra("url");
new DownloadCarDetail().execute(url);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View v = inflater.inflate(R.layout.fragment_service_car_list, container, false);
mList = (ListView) v.findViewById(R.id.list);
mList.setAdapter(adapter);
for (CarDetail car : carDetailList) {
// START LOADING IMAGES FOR EACH STUDENT
car.loadImage(adapter);
}
return v;
}
class DownloadCarDetail extends AsyncTask<String, String, ArrayList<CarDetail>> {
#Override
protected ArrayList<CarDetail> doInBackground(String... params) {
// TODO Auto-generated method stub
ArrayList<CarDetail> carDetailList = JsonParser.parseJson(params[0]);
return carDetailList;
}
#Override
protected void onPostExecute(ArrayList<CarDetail> carDetailList) {
// TODO Auto-generated method stub
ServiceCarListFragment.this.carDetailList = carDetailList;
Log.d("dccs", String.valueOf(ServiceCarListFragment.this.carDetailList.size()));
adapter = new CarListAdapter(getActivity(), ServiceCarListFragment.this.carDetailList);
Log.d("dccs", String.valueOf((adapter.getCount())));
}
}
}
CustomAdapter
public class CarListAdapter extends BaseAdapter {
private ArrayList<CarDetail> items = new ArrayList<CarDetail>();
private Context context;
public CarListAdapter(Context context, ArrayList<CarDetail> items) {
this.context = context;
this.items = items;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return items.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Log.d("Inside", "GetView");
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
ViewHolder holder = null;
CarDetail car = items.get(position);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.car_list_row, null);
holder = new ViewHolder();
holder.tvCarName = (TextView) convertView.findViewById(R.id.tvCarName);
holder.tvDailyPriceValue = (TextView) convertView.findViewById(R.id.tvWeeklyPriceValue);
holder.tvWeeklyPriceValue = (TextView) convertView.findViewById(R.id.tvWeeklyPriceValue);
holder.imgCar = (ImageView) convertView.findViewById(R.id.imgCar);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tvCarName.setText(car.getCarName());
if (car.getImage() != null) {
holder.imgCar.setImageBitmap(car.getImage());
} else {
// MY DEFAULT IMAGE
holder.imgCar.setImageResource(R.drawable.ic_action_call);
}
return convertView;
}
static class ViewHolder {
TextView tvCarName;
TextView tvDailyPriceValue;
TextView tvWeeklyPriceValue;
ImageView imgCar;
}
}
The only reasons getView is not called are:
getCount returns 0.
you forget to call setAdapter on the ListView.
If the ListView's visibility (or its container's visibility) is GONE. Thanks to #TaynãBonaldo for the valuable input.
ListView is not attached to any viewport layout. That is, mListView = new ListView(...) is used without myLayout.addView(mListView).
In the onPostExcute, after you create a new instance of CarListAdapter I will suggest you to update the new instance to your ListView. Indeed you need to call again
mList.setAdapter(adapter);
Edit: setAdapter should be always called on the ui thread, to avoid unexpected behaviours
Edit2:
The same applies to RecyclerView. Make sure that
getItemCount is returning a value grater than 0 (usually the dataset size)
both setLayoutManager and setAdapter have to be called on the UI Thread
The visibility of the widget has to be set to VISIBLE
you must verify that the list has elements might have an error when adding items to your list .
To verify , use the method:
adapter.getCount();
I faced similar problem. Here is a simple work around to solve it:
In your onCreateView, you will have to wait before the view gets created. So change your lines from this:
mList = (ListView)v.findViewById(R.id.list);
mList.setAdapter(adapter);
CHANGE THE ABOVE TWO LINES INTO:
mList = (ListView)v.findViewById(R.id.list);
mList.post(new Runnable() {
public void run() {
mList.setAdapter(adapter);
}
});
Hope this will help others who would run into similar problem
You are missing the super class in the constructor. See my example below:
public AppDataAdapter(Activity a, int textViewResourceId, ArrayList<AppData> entries) {
super(a, textViewResourceId, entries);
this.entries = entries;
this.activity = a;
}
What you have been doing is
In your adapter
public CarListAdapter(Context context , ArrayList<CarDetail> items) {
this.context = context;
this.items = items;
}
in your Fragment
adapter = new CarListAdapter(getActivity(),ServiceCarListFragment.this.carDetailList);
I hope you will be using FragmentActivity
You need to call
adapter = new CarListAdapter(YOUR_ACTIVITY_CONTEXT, carDetailList);
where YOUR_ACTIVITY_CONTEXT will be your FragmentActivity
I had the same problem. And after trying all tips above my getView was still not being called. So I tried to remove the ScrollView that I used outside the ListView. Then the getView worked well. Just for add one more posibility. I Hope help someone.

Start chronometer on each row of Listview in android

I have list items on one list layout among items i have there is a chronometer that i need to start on each row ,other items come from database, but when activity launches Chronometer stays on 00:00. Please help me , i did many research some tell me that in can use adapter but i am not familiar with it, i don't know if there is not another way to do it without using adapter .
MainActivity .java:
private ArrayList<HashMap<String, String>> userList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myList = (ListView)findViewById(R.id.listView);
inflatedView =
getLayoutInflater().inflate(R.layout.payement_timing_list_adapter_view, null);
chronometer = (Chronometer)
inflatedView.findViewById(R.id.chronometer);
if (userList.size() != 0) {
//Set the User Array list in ListView
adapter = new SimpleAdapter(getApplicationContext(), userList, R.layout.payement_timing_list_adapter_view,
new String[]{"Driver_fullname", "plate_no", "parking_name"},
new int[]{R.id.drivername, R.id.plateno, R.id.pname});
myList.setAdapter(adapter);
}
myList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent,
View view, int position, long id) {
Log.d("My POSITION",""+position);
((Chronometer)inflatedView.findViewById(R.id.chronometer)).myList.
(position).start();
chronometer.start();
}
});
You will need to use a custom adapter for your ListView, and declare the Chronometer in the getView method for each row.
A custom adapter could be onle like this:
public class CustomAdapter extends BaseAdapter{
ArrayList<HashMap<String, String>> users;
Context context;
private static LayoutInflater inflater=null;
public CustomAdapter(MainActivity mainActivity, ArrayList<HashMap<String, String>> usersList) {
// TODO Auto-generated constructor stub
users = usersList;
context=mainActivity;
inflater = ( LayoutInflater )context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return items.length;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public class Holder
{
TextView tv;
...
Chronometer cr;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Holder holder=new Holder();
View rowView;
//Create a custom layout for your row view with the chronometer on it and get it here
rowView = inflater.inflate(R.layout.custom_row_item, null);
holder.tv=(TextView) rowView.findViewById(R.id.textView1);
...
holder.cr=(Chronometer) rowView.findViewById(R.id.chronometer);
cr.start();
holder.tv.setText("GET THE TEXT YOU NEED FROM USERS LIST HERE");
return rowView;
}
}
Then declare and use your custom adapter like:
CustomAdapter myAdapter = new CustomAdapter(YourActivity.this, userList);
myList.setAdapter(myAdapter);
Hope it helps :)

Know the clicked checkBox Items in ListView?

I have a custom List view with some elements and a checkbox. When I click on a button. I want to know the positions of the elements which have been checked.
The following below is my code
public class Results extends ListActivity implements OnClickListener{
String[] donorName,donorPhone;
int totNumber;
Button callBut;
ListView listView;
List<RowItem> rowItems;
public static void main(String[] args) {
// TODO Auto-generated method stub
}
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.results);
Intent intent = getIntent();
donorName = intent.getStringArrayExtra("name");
donorPhone = intent.getStringArrayExtra("phone");
totNumber = intent.getExtras().getInt("totDonors");
callBut = (Button)findViewById(R.id.callBut);
callBut.setOnClickListener(this);
rowItems = new ArrayList<RowItem>();
for (int i = 0; i < totNumber; i++) {
RowItem item = new RowItem(donorName[i], donorPhone[i]);
rowItems.add(item);
}
ListAdapter adapter = new MySimpleArrayAdapter(this,
R.layout.list_item, rowItems);
setListAdapter(adapter);
};
///////////////////////////////////////////////////////////////////////////////////////////
public static class MySimpleArrayAdapter extends ArrayAdapter<RowItem> implements OnCheckedChangeListener {
Context context;
static List<RowItem> donorList = new ArrayList<RowItem>();
public MySimpleArrayAdapter(Context context, int resourceId,
List<RowItem> donorList) {
super(context, resourceId, donorList);
this.context = context;
this.donorList = donorList;
}
private class ViewHolder {
Button donorCall,exp;
TextView donorName;
TextView donorPhone;
CheckBox chkBox;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
final RowItem rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.donorName = (TextView) convertView.findViewById(R.id.donorName);
holder.donorPhone = (TextView) convertView.findViewById(R.id.donorPhone);
holder.donorCall = (Button) convertView.findViewById(R.id.donorCall);
holder.chkBox = (CheckBox) convertView.findViewById(R.id.chkBox);
convertView.setTag(holder);
}
else
holder = (ViewHolder) convertView.getTag();
holder.donorPhone.setText(rowItem.getdonorPhoneS());
holder.donorName.setText(rowItem.getdonorNameS());
holder.chkBox.setTag(position);
holder.chkBox.setOnCheckedChangeListener(this);
holder.donorCall.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Log.d("Button Clicked",position+"");
Intent startCall = new Intent(Intent.ACTION_CALL);
startCall.setData(Uri.parse("tel:" + rowItem.getdonorPhoneS()));
context.startActivity(startCall);
}
});
return convertView;
}
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
int position = (Integer) buttonView.getTag();
if (isChecked) {
donorList.get(position).setSelected(true);
Log.d("Tag",donorList.get(position).isSelected()+"");
} else {
buttonView.setSelected(false);
Log.d("Unchecked",isChecked+"");
}
notifyDataSetChanged();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
String msgRecipient;
Log.d("MSg","Button Clicked");
for (int x = 0; x<totNumber;x++){
if(MySimpleArrayAdapter.donorList.get(x).isSelected()){
Log.d("position Checked",x+"");
}
else
Log.d("position UnChecked",x+"");
}
}
}
When I click the checkbox on an item I get true in Log .But when I click on the Button all the elements are shown under unchecked.
you forgot to set the checked state of the checkboxes inside the getView , so if you scroll down/up you will get the old checkboxes being shown without being updated.
what you need to do is to have a set of integers (or a sparseIntArray, which is better), add items positions into it when the checkbox is checked, and remove when they get unchecked.
in order to get all of the checked checkboxed, just use this set of integers...
You can try this to know selected item position in adapter.
for(int i=0;i<MySimpleArrayAdapter.mCheckStates.size();i++)
{
if(MySimpleArrayAdapter.mCheckStates.get(i)==true)
{
// i is the position of a checked items
}
}
There may be a couple of problems going on here.
Firstly, you'll want to make sure you have the setChoiceMode of your ListView (internal to ListActivity) to something other than the default value. Ie:
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
See for more details: Losing current selection when calling adapter.notifyDataSetChanged()
Additionally, your call to notifyDataSetChanged() may be causing your selections to reset as described here: Losing current selection of list item after updating the listview items using notifyDataSetChanged

How to send ArrayList into BaseAdapter Android

I want to display my JSON into gridview, before it.. i displayed my JSON into ListView, and it works. but in BaseAdapter, i don't know how to send my JSON that I have put into ArrayList into Base Adapter
so this is my source code :
Activity :
public class MainActivity extends ListActivity {
List AgenList = new ArrayList();
boolean boolStatusKoneksi=true;
private ProgressDialog Dialog;
protected Context applicationContext;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new AgenAsyncTask().execute();
GridView gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new AgenAdapter(this));
}
public class AgenAsyncTask extends AsyncTask<String, String, String>
{
#Override
protected void onPreExecute() {
super.onPreExecute();
Dialog = new ProgressDialog(MainActivity.this);
Dialog.setMessage("Mohon Tunggu sebentar...");
Dialog.setIndeterminate(false);
Dialog.setCancelable(true);
Dialog.show();
}
protected String doInBackground(String... args) {
String url = ("http:10.10.2/selectAgent.htm");
try{
JSONParser j=new JSONParser();
JSONArray jsonArray = j.takeJson(url);;
for(int i =0; i<jsonArray.length(); i++){
JSONObject c = jsonArray.getJSONObject(i);
HashMap<String, String> map = new HashMap<String, String>();
if (c.has("atasan"))
map.put("atasan", c.get("atasan").toString());
if (c.has("nama_agen"))
map.put("nama_agen", c.get("nama_agen").toString());
if (c.has("kode_agen"))
map.put("kode_agen", c.get("kode_agen").toString());
if (c.has("no_aaji"))
map.put("no_aaji", c.get("no_aaji").toString());
if (c.has("jenis"))
map.put("jenis", c.get("jenis").toString());
AgenList.add(map);
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String file_url) {
}
}
This is my BaseAdapter :
public class AgenAdapter extends BaseAdapter {
public AgenAdapter(MainActivity mainActivity) {
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return 0;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layout = getLayoutInflater();
View view= layout.inflate(R.layout.list_item,parent,false);
TextView ATASAN = (TextView) findViewById(R.id.atasan);
TextView NAMA_AGEN= (TextView) findViewById(R.id.nama_agen);
TextView KODE_AGEN= (TextView) findViewById(R.id.kode_agen);
TextView NO_AAJI= (TextView) findViewById(R.id.no_aaji);
TextView JENIS= (TextView) findViewById(R.id.jenis);
return view;
}
}
}
As you see, i have ArrayList named as = AgenList but i haven't put it into my BaseAdapter.
make a parametrized constructor and pass your array list into its paramerts. so your class will be like
public class AgenAdapter extends BaseAdapter {
List<yourObj> list;
Activity a;
public AgenAdapter(Activity activity,List<yourObj> list) {
this.a=activity;
this.list=list;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();///////return size of list
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;///// dont return null here
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;/////////return position as itemID
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layout = getLayoutInflater();
View view= layout.inflate(R.layout.list_item,parent,false);
TextView ATASAN = (TextView) findViewById(R.id.atasan);
TextView NAMA_AGEN= (TextView) findViewById(R.id.nama_agen);
TextView KODE_AGEN= (TextView) findViewById(R.id.kode_agen);
TextView NO_AAJI= (TextView) findViewById(R.id.no_aaji);
TextView JENIS= (TextView) findViewById(R.id.jenis);
return view;
}
}
try this.
gridview.setAdapter(new AgenAdapter(this), AgenList);
and use this line in your onPostExecute() instead of onCreate()
Like this:
#Override
protected void onPostExecute(String file_url) {
gridview.setAdapter(new AgenAdapter(this), AgenList);
}
Have a look at ArrayAdapter. It contains all of the implementation for an Adapter based on an ArrayList.
Make your adapter a subclass of ArrayAdapter, giving a parametrised type. Yours in this case being Map<String, String>
public class ResultAdapter extends ArrayAdapter<Map<String,String>> {
private int mResource;
/**
* #param context
* #param resource
*/
public ResultAdapter(Context context, int resource, ArrayList<Map<String,String>> dataList) {
super(context, resource, dataList);
this.mResource = resource;
}
...
}
Override the getView method of the ArrayAdapter to use to set the data given to the views.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
// If the view is already inflated, reuse it.
// Else inflate the view
if (convertView != null) {
view = convertView;
} else {
//inflate view
final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(mResource, parent, false);
}
TextView ATASAN = (TextView) findViewById(R.id.atasan);
...
//Get data here
Map<String, String> item = getItem(position);
//Set data to the View's e.g.
ATASAN.setText(item.get("ATASAN"));
...
return view;
}

Custom ListView is not updated when items are inserted

I have a custom listview with custom adapter extending BaseAdapter if i add items to this list view in OnCreate method they show up in list, but if i add them from other methods like a packet listener method then items do not show up , on the screen below this listview there is a textbox if i select textbox to entertext using virtual keyboard immediately the listview gets populated with previousely inserted items which didnt show up. This activity is a chat window basically
I have tried calling notifyDataSetChanged, invalidate on Layout or on listview but nothing helped.
What i think is i need to have a way to refresh activity , as same thing must be happening when the virtual keyboard pops up .
Help will be highly appreciated
Thanks
Code:
package com.arounds;
public class ChatActivity extends Activity implements OnClickListener,PacketListener{
private ListView chatView;
private ChatListViewCustomAdapter adapter;
private String user;
private XMPPConnection connection;
private Conversation conv;
private ChatActivity selfRef = this;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat_win);
AroundApplication app = (AroundApplication) this.getApplicationContext();
connection = app.getConnection();
chatView = (ListView) findViewById(R.id.conversationList);
adapter = new ChatListViewCustomAdapter(this);
chatView.setAdapter(adapter);
// set send btn listener
ImageButton send = (ImageButton)findViewById(R.id.imgBtnSend);
send.setOnClickListener(this);
ImageButton smiley = (ImageButton)findViewById(R.id.imgBtnSmiley);
smiley.setOnClickListener(this);
// get the parameter passed by previouse activity
Bundle b = this.getIntent().getExtras();
String temp = b.getString("user");
user = temp;
TextView v = (TextView)this.findViewById(R.id.txtViewTitle_chat);
v.setText(temp);
v = (TextView)this.findViewById(R.id.txtViewDescription_chat);
temp = b.getString("status");
v.setText(temp);
//chatView.setOnItemClickListener(this);
HashMap convs = app.getConversations();
if(convs.containsKey(user) == true)
conv = (Conversation) convs.get(user);
else {
conv = new Conversation();
convs.put(user,conv);
}
PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
connection.addPacketListener(this,filter);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v.getId() == R.id.imgBtnSend)
{
EditText msg = (EditText)this.findViewById(R.id.editChat);
String s = msg.getText().toString();
Message message = new Message(user, Message.Type.chat);
message.setBody(s);
connection.sendPacket(message);
ArrayList<ChatMessage> m = conv.messages;
String currentDate = DateFormat.getDateInstance().format(new Date());
m.add(new ChatMessage(s,currentDate));
adapter.addItem("I said",s,currentDate,Constants.SEND_LIST_TYPE);
//adapter.notifyDataSetChanged();
}
else
{
//View view = this.findViewById(R.id.linerLayoutChat);
chatView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
#Override
public void processPacket(Packet packet) {
// TODO Auto-generated method stub
System.out.println("in");
Message message = (Message) packet;
if (message.getBody() != null) {
System.out.println("in1");
String fromName = StringUtils.parseBareAddress(message.getFrom());
ArrayList<ChatMessage> m = conv.messages;
String currentDate = DateFormat.getDateInstance().format(new Date());
m.add(new ChatMessage(message.getBody(),currentDate));
adapter.addItem(fromName+" said",message.getBody(),currentDate,Constants.REC_LIST_TYPE);
//chatView.postInvalidate();
}
}
}
Adapter class:
public class ChatListViewCustomAdapter extends BaseAdapter
{
public ArrayList<ChatListItem> items;
public Activity context;
public LayoutInflater inflater;
public Boolean temp=false;
public ChatListViewCustomAdapter(Activity context) {
super();
this.context = context;
this.items = new ArrayList<ChatListItem>();
this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
public static class ViewHolder
{
TextView txtViewTitle;
TextView txtViewDescription;
TextView txtViewDate;
}
public void addItem(String title,String desc,String d,int type)
{
ChatListItem item = new ChatListItem(title,desc,d,type);
items.add(item);
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ChatListItem item = items.get(position);
ViewHolder holder;
System.out.println("Title:"+item.title+" type:"+item.type);
if(convertView==null)
{
holder = new ViewHolder();
int type = this.getItemViewType(position);
if(type == 0)
{
convertView = inflater.inflate(R.layout.list_item_even, null);
holder.txtViewTitle = (TextView) convertView.findViewById(R.id.txtViewTitleEven);
holder.txtViewDescription = (TextView) convertView.findViewById(R.id.txtViewDescriptionEven);
holder.txtViewDate = (TextView) convertView.findViewById(R.id.txtViewDateEven);
}
else
{
convertView = inflater.inflate(R.layout.list_item_odd, null);
holder.txtViewTitle = (TextView) convertView.findViewById(R.id.txtViewTitleOdd);
holder.txtViewDescription = (TextView) convertView.findViewById(R.id.txtViewDescriptionOdd);
holder.txtViewDate = (TextView) convertView.findViewById(R.id.txtViewDateOdd);
}
convertView.setTag(holder);
}
else
holder=(ViewHolder)convertView.getTag();
holder.txtViewTitle.setText(item.title);
holder.txtViewDescription.setText(item.desc);
holder.txtViewDate.setText(item.date);
return convertView;
}
#Override
public int getItemViewType(int position) {
ChatListItem item = items.get(position);
return item.type;
}
#Override
public int getViewTypeCount() {
return 2;
}
}
Handle all the updates within your Adapter and ensure you invoke notifyDataSetChanged() after you update it (within your Adapter)?
In cases where notifyDataSetChanged() does not work, re-set the adapter on the ListView by calling ListView.setAdapter() with the same Adapter again. This should refresh the view.
the only thing I can see not right are these methods:
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
These methods should return proper values.
items.get(position) and position respectively.

Categories

Resources