I am trying to set the data to an adapter through an AsyncTask. This has caused alot of grief - Most recently when trying to set the Array Adapter.
The following method is called onPostExecute();
private void setQueues(final JSONObject[] qInfo)
{
queues = new QueueItem[qInfo.length];
for(int i = 0; i < qInfo.length; i++)
{
queues[i] = new QueueItem();
//final int ii = i;
// Formatting the queue title
String name = qInfo[i].optString("name").replace("-", " ");
queues[i].label = name;
try {
if(qInfo[i].getString("active").contains("1"))
{
queues[i].value = true;
}
else
{
queues[i].value = false;
}
}
catch (JSONException e)
{
e.printStackTrace();
}
}
lv.setAdapter(new QueueAdapter(getActivity(),
R.layout.queues_items, queues));
This causes the following exception runtime : link here
EDIT : As requested, here is QueueAdapter :
public class QueueAdapter extends ArrayAdapter<QueueItem>{
Context context;
int layoutResourceId;
QueueItem data[] = null;
public QueueAdapter(Context context, int layoutResourceId, QueueItem[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
QueueHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new QueueHolder();
holder.queueswitch = (Switch)row.findViewById(R.id.queues_item_switch);
holder.txtLabel = (TextView)row.findViewById(R.id.queues_item_text);
row.setTag(holder);
}
else
{
holder = (QueueHolder)row.getTag();
}
QueueItem queue = data[position];
holder.txtLabel.setText(queue.label);
holder.queueswitch.setChecked(queue.value);
return row;
}
static class QueueHolder
{
Switch queueswitch;
TextView txtLabel;
}
}
lv.setAdapter(new QueueAdapter(getActivity(),
R.layout.queues_items, queues));
this snippet should be in try block.. Because If there is JSONException all elements in that array will be null...
I mean to say.. put for loop inside try block and not the oppt.. if you still want to loop when an Exception occurs.. Then Try using Collections instead of array..
Related
I'm trying to create a listview with different items within it. I want to use a switch statement to do this but I'm struggling to produce this I have created this with one XML layout how can I use multiple XML Layouts. I've attached my code - thank you in advance!
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_postlist);
this.generateDummyData();
ListView listView = (ListView) this.findViewById(R.id.postListView);
final PostItemAdapter itemAdapter = new PostItemAdapter(getApplicationContext(), this.generateDummyData());
listView.setAdapter(itemAdapter);
}
private ArrayList<PostData> generateDummyData() {
PostData data = null;
ArrayList<PostData> listData = new ArrayList<PostData>();
for (int i = 0; i < 20; i++) {
data = new PostData();
data.postTitle = "Person " + (i + 1)
+ " Name Surname";
data.postThumbUrl = null;
listData.add(data);
}
return listData;
}
// Get dummy data for Activity Feed
class PostDataTask extends AsyncTask<Integer, Void, Void> {
ArrayList<PostData> recentTracks;
#Override
protected Void doInBackground(Integer... page) {
try {
// Get a page of 15 tracks
// Simplified - getPage accepts 'page' and 'limit' parameters and returns a Collection<Track>
recentTracks = new ArrayList<PostData>();
Thread.sleep(3000);
PostData data = null;
for (int i = 0; i < 10; i++) {
data = new PostData();
data.postTitle = "Person " + (i + 1)
+ " Name is the Post Title from RSS Feed";
data.postThumbUrl = null;
recentTracks.add(data);
}
} catch (Exception e) {
}
return null;
}
#Override
protected void onPostExecute(Void result) {
ListView listView = (ListView) findViewById(R.id.postListView);
PostItemAdapter adapter = ((PostItemAdapter) ((HeaderViewListAdapter) listView.getAdapter()).getWrappedAdapter());
if (adapter == null) {
adapter = new PostItemAdapter(getApplicationContext(), recentTracks);
listView.setAdapter(adapter);
} else {
adapter.addAll(recentTracks);
adapter.notifyDataSetChanged();
}
}
}
public class PostItemAdapter extends ArrayAdapter<PostData> {
private final Context context;
private final ArrayList<PostData> items;
private int currentPage = 0;
public PostItemAdapter(Context context, ArrayList<PostData> recentTrackArrayList) {
super(context, 0, recentTrackArrayList);
this.context = context;
this.items = recentTrackArrayList;
}
public View getView(int position, View convertView, ViewGroup parent) {
View rowView;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.postitem,
parent, false);
}
final PostData item = items.get(position);
rowView = convertView;
ImageView thumbImageView = (ImageView) rowView
.findViewById(R.id.postThumb);
if (items.get(position).postThumbUrl == null) {
thumbImageView.setImageResource(R.drawable.postthumb_loading);
}
TextView postTitleView = (TextView) rowView
.findViewById(R.id.postTitleLabel);
postTitleView.setText(items.get(position).postTitle);
if (position == getCount() - 1) {
currentPage++;
new PostDataTask().execute(currentPage);
}
return convertView;
}
}
}
At first use ViewHolder pattern.
At second make interfase of Item which will include two methods:
getType() - which return the type of your item;
getView(LayoutInflater inflater, View convertView) - which return the view of row. Inside this method create ViewHolder instance, then inflate View parameter to VH and do some action with result view.
. Then create 2 (or how much u need) classes which would implement Item. Define methods. Then in ListAdapter in getView() call getView() of items and return it to list.
Using the view holder pattern won't work if your items are completely different.
For every item, you need to check what kind of item you want to display and inflate a different view depending on it (for example, using a switch as you said)
I have a custom array adapter for a ListView. The goal is to have each list item have an individual picture, and that when the user clicks on the item they are taken to a web page. I have the image part working, and there are some stackoverflow answers for where to put the onItemClickListener. It seems it would go in the custom array adapter class But I can't figure out how to access the url from the list item.
Here is the code:
public class Animal
{
int image_resource_id;
String animal_type;
String wikipedia_url;
Animal(int image_resource_id, String animal_type, String wikipedia_url)
{
this.image_resource_id = image_resource_id;
this.animal_type = animal_type;
this.wikipedia_url = wikipedia_url;
}
}
class AnimalViewHolder
{
ImageView animal_image = null;
TextView animal_name = null;
String animal_url = "";
}
class CustomAnimalAdapter extends ArrayAdapter<Animal>
{
Context context;
int layoutResourceId;
Animal data[] = null;
public CustomAnimalAdapter(Context context, int layoutResourceId, Animal[] data)
{
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
AnimalViewHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new AnimalViewHolder();
holder.animal_image = (ImageView)row.findViewById(R.id.animal_image);
holder.animal_name = (TextView)row.findViewById(R.id.animal_name);
row.setTag(holder);
}
else
{
holder = (AnimalViewHolder)row.getTag();
}
Animal animal = data[position];
holder.animal_name.setText(animal.animal_type);
holder.animal_image.setImageResource(animal.image_resource_id);
return row;
}
}
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_main);
Animal[] animal_list = {
new Animal(R.drawable.lion, "Lion", "http://en.wikipedia.org/wiki/Lion"),
new Animal(R.drawable.tiger, "Tiger", "http://en.wikipedia.org/wiki/Tiger"),
new Animal(R.drawable.bear, "Bear", "http://en.wikipedia.org/wiki/Bear"),
new Animal(R.drawable.monkey, "Monkey", "http://en.wikipedia.org/wiki/Monkey"),
new Animal(R.drawable.moose, "Moose", "http://en.wikipedia.org/wiki/Moose"),
new Animal(R.drawable.shark, "Shark", "http://en.wikipedia.org/wiki/Shark")
};
CustomAnimalAdapter adapter = new CustomAnimalAdapter(this,
R.layout.row_item, animal_list);
list_view_1 = (ListView)findViewById(R.id.listView1);
list_view_1.setAdapter(adapter);
}
update your adapter getview with
row.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(animal.wikipedia_url));
context.startActivity(browserIntent);
}
});
I am using BaseAdapter for loading the data in gridview. When the data is loaded to the gridview, and the user tries to scroll, I used to get incorrect data. In order to fix that I used ViewHolder. That actually fixed the issue, however, when the users click any of the data in the gridview, instead of getting the correct id from the item, all the items are returning a similar id number.
public class ProductAdapter extends BaseAdapter {
// Context context;
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater = null;
ViewHolder holder;
int layoutResourceId;
Event event;
EventDBAdapter eventDb;
int id;
PersianCalendar sc;
String Today;
SharedPreferences Prefrences_test;
String date, userid;
String newText = "";
String test;
int status;
MoodsDBAdapter moodsDBAdapter;
Mood mood;
ArrayList<MoodsNote> arrayMoodsNote;
MoodsNoteDBAdapter moodsNoteDBAdapter;
MoodsNote moodsNote;
public ProductAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
// this.context = context;
eventDb = new EventDBAdapter(activity);
event = new Event();
moodsDBAdapter = new MoodsDBAdapter(activity);
mood = new Mood();
moodsNoteDBAdapter = new MoodsNoteDBAdapter(activity);
data = d;
// this.layoutResourceId = layoutResourceId;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Prefrences_test = activity.getSharedPreferences("temp", 0);
date = Prefrences_test.getString("date", "");
userid = Prefrences_test.getString("userid", "");
sc = new PersianCalendar();
Today = date;
eventDb = new EventDBAdapter(activity.getApplicationContext());
event = eventDb.getName(Today);
try {
arrayMoodsNote = moodsNoteDBAdapter.getItems(event.getID());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
holder = null;
HashMap<String, String> song = new HashMap<String, String>();
song = data.get(position);
if (vi == null) {
vi = inflater.inflate(R.layout.note_mood_list_item, null);
holder = new ViewHolder();
holder.title = (TextView) vi.findViewById(R.id.mood_text);
holder.txt_id = (TextView) vi.findViewById(R.id.txt_id_mood);
holder.thumb_image = (ImageView) vi.findViewById(R.id.mood_img);
holder.linear = (LinearLayout) vi.findViewById(R.id.mood_layout);
vi.setTag(holder);
} else {
holder = (ViewHolder) vi.getTag();
}
holder.linear.setBackgroundResource(R.drawable.bg_mood);
//holder.txt_id.setText("");
String titles = song.get("name");
holder.title.setText(titles);
Resources res = activity.getResources();
int resourceId = res.getIdentifier(song.get("icon"), "drawable",
activity.getPackageName());
holder.thumb_image.setBackgroundResource(resourceId);
holder.txt_id.setText(song.get("id"));
try {
for (MoodsNote m : arrayMoodsNote) {
int moodd = m.getMOOD();
if (Integer.parseInt(holder.txt_id.getText().toString()) == moodd)
{
holder.linear.setBackgroundResource(R.drawable.bg_mood_on);
}
}
} catch (Exception e) {
// TODO: handle exception
}
holder.thumb_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Toast.makeText(activity, holder.txt_id.getText().toString(), 0).show();
status = 1;
event = new Event();
int tedad = eventDb.getDate(date);
if (tedad <= 0) {
event = new Event(userid, date);
eventDb.insert(event);
}
event = eventDb.getName(date);
moodsNote = new MoodsNote();
id = 0;
id = Integer.parseInt(holder.txt_id.getText().toString());
// id = rowItem.getID();
int tedadd = moodsNoteDBAdapter.getLastItemID(id);
if (tedadd <= 0)
{
moodsNote.setMOOD(id);
moodsNote.setEVENT(event.getID());
moodsNoteDBAdapter.insert(moodsNote);
holder.linear.setBackgroundResource(R.drawable.bg_mood_on);
}
else {
moodsNoteDBAdapter.deleteId(id);
holder.linear.setBackgroundResource(R.drawable.bg_mood);
}
}
});
return vi;
}
static class ViewHolder {
ImageView thumb_image;
TextView txt_id, title;
LinearLayout linear;
}
I have a class that looks like this:
public class Vizita {
public int icon;
public String titlu;
public String loc;
public String idviz;
public Vizita(){
super();
}
public Vizita(int icon, String titlu, String loc, String idviz) {
super();
this.icon = icon;
this.titlu = titlu;
this.loc = loc;
this.idviz = idviz;
}
}
I use AsyncTask to retrieve a JSON array from a PHP. All works perfect for simple layout of listview. But I want to use a more complex layout, so I designed one that uses all 4 values from Vizita.class above. But I do not know how to set the adapter for it, because the way I try it, gives me errors.
Of course I am trying to do it in onPostExecute, like this:
public class MyActivity extends Activity {
{...}
JSONArray lststat;
{...}
public JSONArray liststatus() {
JSONArray jdata=post.getserverdataX(url_connectX);
return jdata;
}
class asyncpost extends AsyncTask< String, String, String > {
Vizita weather_data[];
....
protected void onPostExecute(String result) {
VizitaAdapter adapter = new VizitaAdapter(MyActivity.this,R.layout.listview_item_row, weather_data);
myListView.setAdapter(adapter);
...}
And in doInBackground I am processing the JSON like this:
lststat = liststatus();
JSONObject json_data;
try {
int length = lststat.length();
Vizita weather_data[] = new Vizita[length];
for (int i = 0; i < length; i++)
{
json_data = lststat.getJSONObject(i);
weather_data[i].titlu =json_data.getString("clientnume");
weather_data[i].idviz =json_data.getString("idvizite");
weather_data[i].loc =json_data.getString("localitate");
}
} catch (Exception e) {
Log.e(null, e.toString());
}
where liststatus() is where I call the asyncTask to retrieve the needed JSONArray.
But I receive a java.lang.NullPointerException in the for loop (if I comment the setAdapter line).
I assume I did not initialize the weather_data array properly ?!?!?
If I (uncomment) set the adapter in onPostExecute I receive a crash error "Force close"
I do not receive any errors in the IDE, seeming that the syntaxes are fine.
Please tell me what am I doing wrong? And how can I fix it?
The code for the VizitaAdapter is bellow
public class VizitaAdapter extends ArrayAdapter<Vizita>{
Context context;
int layoutResourceId;
Vizita data[] = null;
public VizitaAdapter(Context context, int layoutResourceId, Vizita[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
WeatherHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new WeatherHolder();
holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
holder.txtLoco = (TextView)row.findViewById(R.id.txtLocalitate);
holder.txtIdviz = (TextView)row.findViewById(R.id.txtIdVizite);
row.setTag(holder);
}
else
{
holder = (WeatherHolder)row.getTag();
}
Vizita weather = data[position];
holder.txtTitle.setText(weather.titlu);
holder.txtLoco.setText(weather.loc);
holder.txtIdviz.setText(weather.idviz);
holder.imgIcon.setImageResource(weather.icon);
return row;
}
static class WeatherHolder
{
ImageView imgIcon;
TextView txtTitle;
TextView txtLoco;
TextView txtIdviz;
}
}
Probably you forgot initialize Vizita object in loop:
json_data = lststat.getJSONObject(i);
weather_data[i] = new Vizita();
weather_data[i].titlu =json_data.getString("clientnume");
weather_data[i].idviz =json_data.getString("idvizite");
weather_data[i].loc =json_data.getString("localitate");
The title of this question is same but technical issue are different.
Hi i am trying to get data from SQLite but i am able to show only last item in listview. I tried different- different solution but not getting success.
Problem is not getting item from SQLite(I am able to fetch all item) but showing item using adapter in listview.
Here is my code.
ListActivity.java
db=new DBHelper(getBaseContext());
db.getWritableDatabase();
try {
final DBHelper m = new DBHelper(getBaseContext());
final List<GetSet> NotesWiseProfile = m.getBabyDetails();
for (final GetSet cn : NotesWiseProfile) {
counter++;
String babyName = cn.getBabyName();
String babyImage = cn.getBabyImage();
int babyId = cn.getBabyId();
BabyData baby_data[] = new BabyData[]
{
new BabyData(R.drawable.ic_launcher, babyName,babyId),
};
adapter = new MobileArrayAdapter(this,
R.layout.list_row, baby_data);
listView1.invalidateViews();
listView1.setAdapter(adapter);
}
}
catch (Exception e) {
}
BabyData.java
public class BabyData {
public int icon;
public String title;
public int babyid;
public BabyData(){
super();
}
public BabyData(int icon, String title,int babyId) {
super();
this.icon = icon;
this.title = title;
babyid = babyId;
}
}
MobileArrayAdapter.java
public class MobileArrayAdapter extends ArrayAdapter<BabyData>{
Context context;
int layoutResourceId;
BabyData data[] = null;
public MobileArrayAdapter(Context context, int layoutResourceId, BabyData[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
DataHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new DataHolder ();
holder.imgIcon = (ImageView)row.findViewById(R.id.imvBabyFace);
holder.txtTitle = (TextView)row.findViewById(R.id.tvbabyNameList);
holder.txtBabyId = (TextView)row.findViewById(R.id.tvBabyId);
row.setTag(holder);
}
else
{
holder = (DataHolder )row.getTag();
}
BabyData weather = data[position];
holder.txtTitle.setText(weather.title);
holder.txtBabyId.setText(String.valueOf(weather.babyid));
holder.imgIcon.setImageResource(weather.icon);
return row;
}
static class DataHolder
{
ImageView imgIcon;
TextView txtTitle;
TextView txtBabyId;
}
}
I don't understand what's wrong in my code. Please give me any hint or reference.
Thanks in Advance.
Put the listview declarations out of the for loop, something like:
BabyData baby_data[] = new BabyData[NotesWiseProfile.size()];
for (final GetSet cn : NotesWiseProfile) {
String babyName = cn.getBabyName();
String babyImage = cn.getBabyImage();
int babyId = cn.getBabyId();
baby_data[counter] = new BabyData(R.drawable.ic_launcher, babyName,babyId);
counter++;
}
adapter = new MobileArrayAdapter(this,
R.layout.list_row, baby_data);
listView1.invalidateViews();
listView1.setAdapter(adapter);
I think you should use a field for storing you babies. Currrently, you are using a local Baby array for that. As far as I know, the ListView always gets its data from the array you passed to it (invalidating it causes the ListView to look up that data again.
To recap: Store your array as a field - if data changes, update the array and call notifyDatasetChanged() on your adapter, which will cause your ListView to reload the data.