I have been trying to sort out this class file all day and I have run into yet more problems. I believe this class file is setup completely wrong. I think the AsyncTask is incorrect as well as my onCreateView is I believe as well. What I am trying to do is download a XML file from the internet and put the information into areas for the ListView to use. I have had it working but I decided to change it for use as a fragment and that is when the problems have arose as you cannot have the same stuff for an activity as a fragment obviously. Here is my class file and as I do not understand where I have gone wrong in terms of the AsyncTask especially could I have some help. Thanks for helping me out!
Errors: The parser on the AsyncTask cannot have the symbol resolved and the xml string is incorrect for what I want to use it for. I really am lost here now.
CustomizedListView.class
public class CustomizedListView extends Fragment {
// All static variables
static final String URL = "http://api.androidhive.info/music/music.xml";
// XML node keys
static final String KEY_SONG = "song"; // parent node
static final String KEY_ID = "id";
static final String KEY_TITLE = "title";
static final String KEY_ARTIST = "artist";
static final String KEY_DURATION = "duration";
static final String KEY_THUMB_URL = "thumb_url";
ListView list;
LazyAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
final View v = inflater.inflate(R.layout.list_row, container, false);
list = (ListView) v.findViewById(R.id.game_list);
return v;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
new TheTask().execute();
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_SONG);
// looping through all song nodes <song>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST));
map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
// adding HashList to ArrayList
songsList.add(map);
}
// Getting adapter by passing xml data ArrayList
adapter=new LazyAdapter(getActivity(), songsList);
list.setAdapter(adapter);
// Click event for single list row
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
}
});
}
}
class TheTask extends AsyncTask<Void,Void,Void> {
static final String URL = "http://api.androidhive.info/music/music.xml";
static final String xml = xml;
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
String xml = parser.getXmlFromUrl(URL);
return null;
}
}
Logcat Error after code change:
07-20 20:48:18.941 22942-22942/com.example.app E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.NullPointerException
at com.example.app.CustomizedListView.onCreate(CustomizedListView.java:52)
at android.support.v4.app.Fragment.performCreate(Fragment.java:1437)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:877)
at android.support.v4.app.FragmentManagerImpl.performPendingDeferredStart(FragmentManager.java:807)
at android.support.v4.app.Fragment.setUserVisibleHint(Fragment.java:801)
at android.support.v4.app.FragmentPagerAdapter.setPrimaryItem(FragmentPagerAdapter.java:130)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1062)
at android.support.v4.view.ViewPager.populate(ViewPager.java:911)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1432)
at android.view.View.measure(View.java:15525)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4825)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
at android.view.View.measure(View.java:15525)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:847)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
at android.view.View.measure(View.java:15525)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4825)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2434)
at android.view.View.measure(View.java:15525)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1874)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1089)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1265)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:989)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4351)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
at android.view.Choreographer.doCallbacks(Choreographer.java:562)
at android.view.Choreographer.doFrame(Choreographer.java:532)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5227)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
at dalvik.system.NativeStart.main(Native Method)
You were doing it completely wrong.. I would suggest to go and read about Multi Threaded Programming and Asynchronous Tasks a little which will help you a lot around this..
You had many issues in the code, I fixed a lot of things but I will mention the most important ones and the ones I actually remember :p
If you want to use globally defined variables then your AsyncTask class should be defined within your Activity class.. Which in your case was defined outside
When you execute a AsyncTask, it creates a new thread and the commands in the new background thread are ran independently from the ones the UI thread. My point is that, many people think the UI thread will stop for the Background thread to finish working. Which is wrong and also a common problem within programmers.
You really hate indentation. Don't you? It makes other programmers go nuts, when reading a bad indented code, which leads into your question remaining unanswered.
Here is the fixed code:
public class CustomizedListView extends Fragment {
// All static variables
static final String URL = "http://api.androidhive.info/music/music.xml";
// XML node keys
static final String KEY_SONG = "song"; // parent node
static final String KEY_ID = "id";
static final String KEY_TITLE = "title";
static final String KEY_ARTIST = "artist";
static final String KEY_DURATION = "duration";
static final String KEY_THUMB_URL = "thumb_url";
ListView list;
ArrayList<HashMap<String, String>> songsList;
View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
final View v = inflater.inflate(R.layout.list_row, container, false);
list = (ListView) v.findViewById(R.id.game_list);
view = v;
return v;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new TheTask().execute();
// Click event for single list row
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
}
});
}
class TheTask extends AsyncTask<Void, Void, Void> {
static final String URL = "http://api.androidhive.info/music/music.xml";
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
songsList = new ArrayList<HashMap<String, String>>();
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_SONG);
// looping through all song nodes <song>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST));
map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
// adding HashList to ArrayList
songsList.add(map);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// Getting adapter by passing xml data ArrayList
LazyAdapter adapter = new LazyAdapter(getActivity(), songsList);
((ListView) view.findViewById(R.id.game_list)).setAdapter(adapter);
super.onPostExecute(result);
}
}
}
Related
I have a custom list adapter that reads in data from a xml file that is hosted online, each one is for a different article. My question is how do I make each list item open a different corresponding article? The articles will be hosted online.
Thank you in advance.
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import java.util.ArrayList;
import java.util.HashMap;
public class CustomizedListView extends Fragment { // All static variables
// XML node keys
static final String KEY_SONG = "song"; // parent node
static final String KEY_ID = "id";
static final String KEY_ARTIST = "artist";
static final String KEY_DURATION = "duration";
static final String KEY_THUMB_URL = "thumb_url";
ListView list;
LazyAdapter adapter;
ArrayList<HashMap<String, String>> songsList;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.news, container, false);
songsList = new ArrayList<HashMap<String, String>>();
list=(ListView) rootView.findViewById(R.id.list);
new RetrieveXML().execute(URL);
// Getting adapter by passing xml data ArrayList
// Click event for single list row XMLParser parser = new XMLParser();
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
}
});
return rootView;
}
class RetrieveXML extends AsyncTask<String, Void, String> {
private Exception exception;
XMLParser parser = new XMLParser();
protected String doInBackground(String... urls) {
try {
return parser.getXmlFromUrl(urls[0]);
} catch (Exception e) {
this.exception = e;
return null;
}
}
protected void onPostExecute(String xml) {
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_SONG);
// looping through all song nodes <song>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST));
map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_ID));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
// adding HashList to ArrayList
songsList.add(map);
}
adapter=new LazyAdapter(getActivity(), songsList);
list.setAdapter(adapter);
}
}
}
You have implemented:
onItemClick()
In this you get the position of item in the list as parameter. here you can write a switch case to accomplish your task. This function gets triggered when any listitem is clicked.
Something like this you can do:
private string[] mArticles={
"abc",
"def",
"ghi",
"jkl"
};
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
openArticle(mArticles[position]);
}
While creating the string array keep appropriate artile link for each item position.
I want to use AsynTask to do custom list with xml from url. I am novice so I don´t know how to structure this properly. When the fragment start doesn´t display nothing. I am using Swipe views with fragments but I don´t know how correct the issue
public class UltimasFragment extends Fragment {
static final String URL = "http://myurl.com/songs";
// XML node keys
static final String KEY_SONG = "songs"; // parent node
static final String KEY_ID = "id_song";
static final String KEY_TITLE = "name";
static final String KEY_THUMB_URL = "picture";
static final String KEY_ARTIST = "duration";
View view;
ListView list;
LazyAdapter adapter;
private ProgressDialog dialog;
public ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.ultimas, container, false);
new MiTarea().execute();
list=(ListView) view.findViewById(R.id.lista);
// Getting adapter by passing xml data ArrayList
//adapter=new LazyAdapter(this, songsList);
adapter=new LazyAdapter(getActivity(), songsList);
list.setAdapter(adapter);
// Click event for single list row
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String idrecibida =songsList.get(+position).get("id_song");
String nombrerecibido =songsList.get(+position).get("name");
String caratularecibida =songsList.get(+position).get("picture");
String nuestraoprecibida =songsList.get(+position).get("duration");
}
});
return view;
}
private class MiTarea extends AsyncTask<String, String, String>{
protected void onPreExecute() {
dialog = new ProgressDialog(getActivity());
dialog.setMessage("Actualizando...");
dialog.setIndeterminate(false);
dialog.setCancelable(true);
dialog.show();
}
protected String doInBackground(String... args) {
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_SONG);
// looping through all song nodes <song>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST));
songsList.add(map);
}
return xml;
}
protected void onPostExecute(String bytes) {
dialog.dismiss();
// adding HashList to ArrayList
}
}
}
Here is how to impement async task
http://developer.android.com/reference/android/os/AsyncTask.html
The preExecute method allow you to perform operations before starting the job you want to do asyncronously.
the doInBackground method is here to do your async job.
the on postExecute method will receive what doInBackground returns if it returns something.
if you need to pass parameters to your class like a context, my advice is to make a constructor and passing parameters to it ;)
hope it helped.
regards.
The three parameters are: the parameter type of doInBackground, the parameter type of onProgressUpdate and the parameter type of onPostExecute.
See here the usage:
http://developer.android.com/reference/android/os/AsyncTask.html
Remember to call setReteainInstance(true) in the fragment in this case, because if the fragment is remove you lost the reference to the AsyncTask.
I found this custom listview tutorial from androidhive and i tried to implement onclick with intent showing the values in the custom listview. Whenever i click on the items, the app crashed. please help!
CustomListView.Java
public class CustomizedListView extends Activity {
// All static variables
static final String URL = "http://myurl/Announcement.xml";
// XML node keys
static final String KEY_ANNOUNCEMENT = "announcement"; // parent node
static final String KEY_ID = "id";
static final String KEY_TITLE = "title";
static final String KEY_INFORMATION = "information";
static final String KEY_DATE = "date";
static final String KEY_ICON = "icon";
ListView list;
LazyAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_ANNOUNCEMENT);
// looping through all song nodes <song>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_INFORMATION, parser.getValue(e, KEY_INFORMATION));
map.put(KEY_DATE, parser.getValue(e, KEY_DATE));
map.put(KEY_ICON, parser.getValue(e, KEY_ICON));
// adding HashList to ArrayList
songsList.add(map);
}
list=(ListView)findViewById(R.id.list);
// Getting adapter by passing xml data ArrayList
adapter=new LazyAdapter(this, songsList);
list.setAdapter(adapter);
// Click event for single list row
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// getting values from selected ListItem
String title = ((TextView) view.findViewById(R.id.title)).getText().toString();
String information = ((TextView) view.findViewById(R.id.information)).getText().toString();
String date = ((TextView) view.findViewById(R.id.date)).getText().toString();
String tag = view.getTag().toString();
// Starting new intent
Intent intent = new Intent(getApplicationContext(), SingleMenuItemActivity.class);
intent.putExtra("title",KEY_TITLE);
intent.putExtra("information",KEY_INFORMATION);
intent.putExtra("date",KEY_DATE);
startActivity(intent);
}
});
}
LazyAdapter.Java
public class LazyAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader;
public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(activity.getApplicationContext());
}
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;
if(convertView==null)
vi = inflater.inflate(R.layout.list_row, null);
TextView title = (TextView)vi.findViewById(R.id.title); // title
TextView date = (TextView)vi.findViewById(R.id.duration); // duration
ImageView icon =(ImageView)vi.findViewById(R.id.list_image); // thumb image
HashMap<String, String> song = new HashMap<String, String>();
song = data.get(position);
vi.setTag(song.get(CustomizedListView.KEY_ID));
// Setting all values in listview
title.setText(song.get(CustomizedListView.KEY_TITLE));
date.setText(song.get(CustomizedListView.KEY_DATE));
imageLoader.DisplayImage(song.get(CustomizedListView.KEY_ICON), icon);
return vi;
}
}
SingleMenuItemActivity.Java
public class SingleMenuItemActivity extends Activity {
// XML node keys
static final String KEY_TITLE = "title";
static final String KEY_INFORMATION = "information";
static final String KEY_DATE = "date";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_single_menu_item);
// getting intent data
Intent in = getIntent();
// Get XML values from previous intent
String title = getIntent().getExtras().getString("title");
String information = getIntent().getExtras().getString("information");
String date = getIntent().getExtras().getString("date");
// Displaying all values on the screen
TextView lblName = (TextView) findViewById(R.id.title);
TextView lblCost = (TextView) findViewById(R.id.information);
TextView lblDesc = (TextView) findViewById(R.id.date);
lblName.setText(title);
lblCost.setText(information);
lblDesc.setText(date);
}
}
Logcat
12-07 20:01:36.575: W/dalvikvm(1167): threadid=1: thread exiting with uncaught exception (group=0x4188f898)
12-07 20:01:36.575: E/AndroidRuntime(1167): FATAL EXCEPTION: main
12-07 20:01:36.575: E/AndroidRuntime(1167): java.lang.NullPointerException
12-07 20:01:36.575: E/AndroidRuntime(1167): at com.example.androidhive.CustomizedListView$1.onItemClick(CustomizedListView.java:79)
12-07 20:01:36.575: E/AndroidRuntime(1167): at android.widget.AdapterView.performItemClick(AdapterView.java:301)
12-07 20:01:36.575: E/AndroidRuntime(1167): at android.widget.AbsListView.performItemClick(AbsListView.java:1510)
12-07 20:01:36.575: E/AndroidRuntime(1167): at android.widget.AbsListView$PerformClick.run(AbsListView.java:3333)
12-07 20:01:36.575: E/AndroidRuntime(1167): at android.os.Handler.handleCallback(Handler.java:730)
12-07 20:01:36.575: E/AndroidRuntime(1167): at android.os.Handler.dispatchMessage(Handler.java:92)
12-07 20:01:36.575: E/AndroidRuntime(1167): at android.os.Looper.loop(Looper.java:137)
12-07 20:01:36.575: E/AndroidRuntime(1167): at android.app.ActivityThread.main(ActivityThread.java:5419)
12-07 20:01:36.575: E/AndroidRuntime(1167): at java.lang.reflect.Method.invokeNative(Native Method)
12-07 20:01:36.575: E/AndroidRuntime(1167): at java.lang.reflect.Method.invoke(Method.java:525)
12-07 20:01:36.575: E/AndroidRuntime(1167): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187)
12-07 20:01:36.575: E/AndroidRuntime(1167): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
12-07 20:01:36.575: E/AndroidRuntime(1167): at dalvik.system.NativeStart.main(Native Method)
I want to add populate my listview using arrayadapter, im currently using simpleadapter. the reason i want to change my adapter is so that i can use the method notifyDataSetChanged(),
so can anyone show me how to do that using my codes below? i would really appreciate it
public class AndroidXMLParsingActivity extends ListActivity {
// All static variables
static final String URL = "https://news.instaforex.com/news";
// XML node keys
static final String KEY_ITEM = "item"; // parent node
static final String KEY_TITLE = "title";
static final String KEY_PUBDATE = "pubDate";
static final String KEY_DESCRIPTION = "description";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ArrayList<HashMap<String, Spanned>> menuItems = new ArrayList<HashMap<String, Spanned>>();
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_ITEM);
// looping through all item nodes <item>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, Spanned> map = new HashMap<String, Spanned>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_TITLE, Html.fromHtml(parser.getValue(e, KEY_TITLE)));
map.put(KEY_PUBDATE, Html.fromHtml(parser.getValue(e, KEY_PUBDATE)));
map.put(KEY_DESCRIPTION, Html.fromHtml(parser.getValue(e, KEY_DESCRIPTION)));
// adding HashList to ArrayList
menuItems.add(map);
}
// Adding menuItems to ListView
ListAdapter adapter = new SimpleAdapter(this, menuItems,
R.layout.list_item,
new String[] { KEY_TITLE, KEY_PUBDATE }, new int[] {
R.id.name, R.id.cost });
setListAdapter(adapter);
// selecting single ListView item
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String title = menuItems.get(position).get(KEY_TITLE).toString();
String pubDate = menuItems.get(position).get(KEY_PUBDATE).toString();
String description= menuItems.get(position).get(KEY_DESCRIPTION).toString();
System.out.println("PubDate==>"+pubDate+"\n Description===>"+description);
// Starting new intent
Intent in = new Intent(getApplicationContext(), SingleMenuItemActivity.class);
in.putExtra(KEY_TITLE, title);
in.putExtra(KEY_PUBDATE, pubDate);
in.putExtra(KEY_DESCRIPTION, description);
startActivity(in);
}
});
}
}
notifyDataSetChanged() is a BaseAdapter method, the parent class of SimpleAdapter and ArrayAdapter. SimpleAdapter and ArrayAdapter are different mainly with respect to the data provided to the AdapterView. While a SimpleAdapter is backed by XML data, an ArrayAdapter is backed by an array of arbitrary data.
In other words there's no need to change the type of adapter.
Now the documentation states that a SimpleAdapter is "an easy adapter to map static data to views" which is discussed in more detail e.g. here. But fact is that a SimpleAdapter works with dynamic data too.
If you still want to switch to an ArrayAdapter then you have to overwrite the ArrayAdapter's getView() method because an ArrayAdapter supports only a single TextView per row (unlike the SimpleAdapter that supports mapping of multiple values to multiple Views for a single row).
There are numerous tutorials on ArrayAdapter out there, e.g. this one:
http://www.vogella.com/articles/AndroidListView/article.html#adapterown_example.
I am building song list application. I want to display splash screen while loading data. For that use I set an AsyncTask combined with ViewSwitcher to switch xml layout beetween splash screen (just logo and circle progressbar) and main screen. The problem is when it comes to puting data in ListView, I am using BaseAdapter which is in separate class, and it throws error "The Constructor LazyAdapter(Home.LoadViewTask, ArrayList<HashMap<String,String>>) is undefined".
This is source of Home Class which has AsyncTask:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
mBtnNaslovnica = (Button) findViewById(R.id.mBtnNaslovnica);
mBtnNaslovnica.setSelected(true);
new LoadViewTask().execute();
}
//To use the AsyncTask, it must be subclassed
public class LoadViewTask extends AsyncTask<Void, Integer, Void>
{
//A TextView object and a ProgressBar object
private TextView tv_progress;
private ProgressBar pb_progressBar;
//Before running code in the separate thread
#Override
protected void onPreExecute()
{
//Initialize the ViewSwitcher object
viewSwitcher = new ViewSwitcher(Home.this);
/* Initialize the loading screen with data from the 'loadingscreen.xml' layout xml file.
* Add the initialized View to the viewSwitcher.*/
viewSwitcher.addView(ViewSwitcher.inflate(Home.this, R.layout.init, null));
//Set ViewSwitcher instance as the current View.
setContentView(viewSwitcher);
}
//The code to be executed in a background thread.
#Override
protected Void doInBackground(Void... params)
{
ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_SONG);
// looping through all song nodes <song>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST));
map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
// adding HashList to ArrayList
songsList.add(map);
}
list=(ListView)findViewById(R.id.list);
// Getting adapter by passing xml data ArrayList
adapter=new LazyAdapter(this, songsList);
list.setAdapter(adapter);
// Click event for single list row
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
}
});
return null;
}
//After executing the code in the thread
#Override
protected void onPostExecute(Void result)
{
/* Initialize the application's main interface from the 'main.xml' layout xml file.
* Add the initialized View to the viewSwitcher.*/
viewSwitcher.addView(ViewSwitcher.inflate(Home.this, R.layout.main, null));
//Switch the Views
viewSwitcher.showNext();
}
}
//Override the default back key behavior
#Override
public void onBackPressed()
{
//Emulate the progressDialog.setCancelable(false) behavior
//If the first view is being shown
if(viewSwitcher.getDisplayedChild() == 0)
{
//Do nothing
return;
}
else
{
//Finishes the current Activity
super.onBackPressed();
}
}
And this is the source of LazyAdapter class:
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader;
public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(activity.getApplicationContext());
}
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;
if(convertView==null)
vi = inflater.inflate(R.layout.list_row, null);
TextView title = (TextView)vi.findViewById(R.id.title); // title
TextView artist = (TextView)vi.findViewById(R.id.artist); // artist name
TextView duration = (TextView)vi.findViewById(R.id.duration); // duration
ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image); // thumb image
HashMap<String, String> song = new HashMap<String, String>();
song = data.get(position);
// Setting all values in listview
title.setText(song.get(Home.KEY_TITLE));
artist.setText(song.get(Home.KEY_ARTIST));
duration.setText(song.get(Home.KEY_DURATION));
imageLoader.DisplayImage(song.get(Home.KEY_THUMB_URL), thumb_image);
return vi;
}
`
You cannot do any UI modification.. such as setting a label text, modifying list inside a AsyncTask.doInBackground.. because it is a separate thread...
list=(ListView)findViewById(R.id.list);
// Getting adapter by passing xml data ArrayList
adapter=new LazyAdapter(this, songsList);
list.setAdapter(adapter);
// Click event for single list row
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
}
});
you should put that part of the code before you call
new LoadViewTask().execute();
and inside the doInBackground()... as the last line..
put this line..
adapter.notifyDataSetChanged();
Your constructor in first parameter get Activity and you pass instance of LoadViewTask (this referrs to the current instance of LoadViewTask),
instead of this use:
adapter=new LazyAdapter(Home.this, songsList);
Where Home should be name of your activity
The problem is that, for whatever reason, you're requiring an Activity as the first parameter of your constructor. By passing this to the constructor of your adapater you're passing an object of type AsyncTask which is not activity and doesn't have a context. So you should pass an Activity as the an argument in the overridden constructor for LoadViewTask and then use it as the correct argument for your constructor.
Nonetheless be careful when binding a context to an AsyncTask since it may lead to unexpected behaviours (the Activity may not exist anymore when AsyncTask tries to update it). AsyncTask is a very dangerous class to use since it has many synchronization-related flaws.
I hope this might be help,
onPostExecute include (Inside AsyncTask)
ExampleAdapter sectionedAdapter = new EfficientAdapter(ClassInfoThread.this,getBaseContext());
listView.setAdapter(sectionedAdapter);
and in your adapter class add this constructor
public ExampleAdapter(ExampleThread exampleThread,Context context) {
// TODO Auto-generated constructor stub`enter code here`
mInflater = LayoutInflater.from(context);
}