Passing List<classname> to ArrayAdapter - java

The problem is this adapter is giving the error although i have pass the Object array to it.(Read the methods belows then you will find what i want to know from you guys)
This method declares a List of private class objects. Then return that list of object to onPostExecute method.
private class DownloadXmlTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
try {
return loadXmlFromNetwork(urls[0]);
} catch (IOException e) {
return "I/O exception ae hy";
} catch (XmlPullParserException e) {
return "XML pull parser ke exception ae hy";
}
}
#Override
protected void onPostExecute(List<StackOverflowXmlParser.Entry> result) {
//Log.d(TAG,result.toString());
ArrayAdapter<String> adapter;
adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,result);
setListAdapter(adapter);
}
private Object loadXmlFromNetwork(String urlString) throws XmlPullParserException, IOException {
InputStream stream = null;
// Instantiate the parser
StackOverflowXmlParser stackOverflowXmlParser = new StackOverflowXmlParser();
List<StackOverflowXmlParser.Entry> entries = null;
String title = null;
String url = null;
String summary = null;
try {
stream = downloadUrl(urlString);
entries = stackOverflowXmlParser.parse(stream);
} finally {
if (stream != null) {
stream.close();
}
}
for (StackOverflowXmlParser.Entry entry : entries)
{
Log.d(TAG, entry.link + " /" + entry.title);
}
return entries;
}

I think it should be onPostExecute(List<StackOverflowXmlParser.Entry> result)
And you AsyncTask should be
extends AsyncTask<smth, smth, List<StackOverflowXmlParser.Entry> >

ArrayAdapter<String> requires that you provide it a String[] or a List<String>. You are trying to pass in Object[], which is neither String[] nor List<String>. And, it would appear that you are really trying to populate the ListView with a list of StackOverflowXmlParser.Entry objects, which are not String objects.
My guess is that the right answer is for you to create an ArrayAdapter<StackOverflowXmlParser.Entry> instead of an ArrayAdapter<String>.
Regardless, you need to ensure that the data type in your declaration (String in ArrayAdapter<String>) matches the data type in your constructor parameter that supplies the data to be adapted.

Related

How to create Async Task to build a RSSReader

Before getting down vote. Yes I read the forums before asking this question. RSSReader Async Task
Read that one above but I still don't get it.
The question:
I wrote een RSSReader in Java. This perfectly works in the console prints what I want etc. But in Android it doesn't work because it's not using een Async Task. Now I understood from the Google Documentation that there are three types to be entered AsyncTask something like that. I have no idea how I can implement this in my code. Do I need to make a seperate class extends it with AsyncTask and create and instance of my Reader and in it's doInBackground method call my reader or how do I need to do this.
This is the code of my RSSReader:
public class RSSReader {
//Lists to store headlines, descriptions & images
String url = "http://www.nu.nl/rss/Algemeen";
List<String> titleList;
List<String> descriptionList;
List<String> imageList;
public RSSReader(){
try {
titleList = readRSS(url, "<title>", "</title>");
descriptionList = listFilter(readRSS(url, "<description>", "</description>"), "&nbsp;", "");
imageList = readRSS(url, "<enclosure url \"", "\" length=\"0\" type=\"image/jpeg\"</enclosure>");
}
catch (IOException e){
}
}
public List<String> readRSS(String feedUrl, String openTag, String closeTag) throws IOException, MalformedURLException {
URL url = new URL(feedUrl);
BufferedReader reader= new BufferedReader(new InputStreamReader(url.openStream()));
String currentLine;
List<String> tempList = new ArrayList<String>();
while((currentLine = reader.readLine()) != null){
Integer tagEndIndex = 0;
Integer tagStartIndex = 0;
while (tagStartIndex >= 0){
tagStartIndex = currentLine.indexOf(openTag, tagEndIndex);
if(tagStartIndex >= 0){
tagEndIndex = currentLine.indexOf(closeTag, tagStartIndex);
tempList.add(currentLine.substring(tagStartIndex + openTag.length(), tagEndIndex) + "\n");
}
}
}
tempList.remove(0);
return tempList;
}
public List<String> getDesciptionList(){
return descriptionList;
}
public List<String> getTitleList(){
return titleList;
}
public List<String> getImageList(){
return imageList;
}
public List<String> listFilter(List<String> tempList, String require, String
replace){
//Creates new List
List<String> newList = new ArrayList<>();
//Loops through old list and checks for the 'require' variable
for(int i = 0; i < tempList.size(); i++){
if(tempList.get(i).contains(require)){
newList.add(tempList.get(i).replace(require, replace));
}
else{
newList.add(tempList.get(i));
}
}
return newList;
}
}
In RSSReader#readRSS,you do not check tempList.size()
and do not forget add
<uses-permission android:name="android.permission.INTERNET"/>
to your AndroidManifest.xml
for example
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new RssReaderAsyncTask(new RSSCallBack() {
#Override
public void success(RSSReader rssReader) {
// TODO That Should run on UI Thread if you update UI
// for example
final RSSReader reader = rssReader;
// you can use runOnUiThread or Handler update UI
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Toast
Toast.makeText(MainActivity.this, reader.getTitleList().toString(), Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void failed() {
// TODO That Should run on UI Thread if you update UI
Log.e("RSS", "failed");
}
}).execute("");
}
private class RssReaderAsyncTask extends AsyncTask<String, Integer, Integer> {
private RSSCallBack rssCallBack;
public RssReaderAsyncTask(RSSCallBack rssCallBack) {
this.rssCallBack = rssCallBack;
}
#Override
protected Integer doInBackground(String... params) {
// TODO
try {
RSSReader reader = new RSSReader();
rssCallBack.success(reader);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
rssCallBack.failed();
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
rssCallBack.failed();
e.printStackTrace();
}
return null;
}
}
private interface RSSCallBack {
void success(RSSReader rssReader);
void failed();
}
public class RSSReader {
// Lists to store headlines, descriptions & images
String url = "http://www.nu.nl/rss/Algemeen";
List<String> titleList;
List<String> descriptionList;
List<String> imageList;
public RSSReader() throws MalformedURLException, IOException {
titleList = readRSS(url, "<title>", "</title>");
descriptionList = listFilter(readRSS(url, "<description>", "</description>"), "&nbsp;", "");
imageList = readRSS(url, "<enclosure url \"", "\" length=\"0\" type=\"image/jpeg\"</enclosure>");
}
public List<String> readRSS(String feedUrl, String openTag, String closeTag)
throws IOException, MalformedURLException {
URL url = new URL(feedUrl);
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
String currentLine;
List<String> tempList = new ArrayList<String>();
while ((currentLine = reader.readLine()) != null) {
Integer tagEndIndex = 0;
Integer tagStartIndex = 0;
while (tagStartIndex >= 0) {
tagStartIndex = currentLine.indexOf(openTag, tagEndIndex);
if (tagStartIndex >= 0) {
tagEndIndex = currentLine.indexOf(closeTag, tagStartIndex);
tempList.add(currentLine.substring(tagStartIndex + openTag.length(), tagEndIndex) + "\n");
}
}
}
if (tempList.size() > 0) {
//TODO you do not check it
tempList.remove(0);
}
return tempList;
}
public List<String> getDesciptionList() {
return descriptionList;
}
public List<String> getTitleList() {
return titleList;
}
public List<String> getImageList() {
return imageList;
}
public List<String> listFilter(List<String> tempList, String require, String replace) {
// Creates new List
List<String> newList = new ArrayList<String>();
// Loops through old list and checks for the 'require' variable
for (int i = 0; i < tempList.size(); i++) {
if (tempList.get(i).contains(require)) {
newList.add(tempList.get(i).replace(require, replace));
} else {
newList.add(tempList.get(i));
}
}
return newList;
}
}
}
You are right, you need Asynctask. But it is too much to explain here, it has already been explained very thoroughly here, so you might wanna take a look:
https://stackoverflow.com/a/9671602/3673616
What you need to make sure is to run your network calls in doInBackground, you can manipulate the UI in onPreExcute and after finish in onpostExecute. For more details please visit the link.
Well i assume that you already know the code so in the doInBackground method should be the long running code, like getting information from internet/server etc. You can then return a string with success or error that will be catched from onPostExecute method, where you can just do what ever you like with the result.
So i would say no need for new class just extend async task in this, implement the 2 methods i mentioned and in the methods call the right function that you already have with just a litttle change for returning result.

In which container can I collect Strings to show any of them

I have a LinkedHashMap which fills with data from db with loop "for" string by string and when I try to show the first or the last String, the method can show me only the last String in log. But in application listViewContent is filled fully. So I don't understand why I can't see any string that I want. I need to collect all strings I get from db and compare them in future.
How can I collect all strings and what method should I call to show the string I want to see?Unfortunately I can only retrieve one (and the last instead of the first) string.
Here is my example code :
protected void onCreate(Bundle saveInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FirstMethod();
}
public FirstMethod() {
SecondMethod newMethod = .. // getting data from the second method
}
public SecondMethod() {
public void onResponseReceived(String result) {
try {
...
if (posts != null) {
for (WallPostItem post : posts) { // this loop
//create new map for a post
Map<String, Object> map = new LinkedHashMap<String, Object>();
map.put(ATTRIBUTE_NAME_TEXT, post.text);
PictureItem postPicture = new PictureItem();
map.put(ATTRIBUTE_NAME_IMAGE, postPicture);
map.put(ATTRIBUTE_NAME_DATE, post.date);
sAdapter.notifyDataSetChanged();
};
};
...
List<Map.Entry<String, Object>> list = new ArrayList<Map.Entry<String, Object>>(GlobalMap.entrySet());
Map.Entry<String, Object> firstInsertedEntry = list.get(0);
Log.w("FirstEntryOfMap",""+firstInsertedEntry); // this log shows me the last string instead of the first
}
if (isRefresh) {
isRefresh = false;
lvSimple.setSelectionAfterHeaderView();
}
} catch (Exception e) {
Log.d("exceptions", "problem in get wall post task after post execute: " + e.toString());
}
}
You aren't putting your values into a List, you are putting them into a Map (that preserves key order). I would suggest you create a POJO class,
class MyAttribute {
final String postName;
final PictureItem postPicture;
final Date postDate;
public MyAttribute(String postName, PictureItem postPicture, Date postDate) {
this.postName = postName;
this.postPicture = postPicture;
this.postDate = postDate;
}
public String getPostName() {
return postName;
}
public Date getPostDate() {
return postDate;
}
public PictureItem getPostPicture() {
return postPicture;
}
}
Then you could create a
List<MyAttribute> myAttributes = new ArrayList<>();

AsyncTask Returns Error

I have been trying to parse XML files using Asynctask, following [1] and [2] tutorials. I have implemented a class in my Activity as follows:
private class GetRoutes extends AsyncTask<String, Void, String[]> {
#Override
protected String[] doInBackground(String... urls) {
String[] read;
try{
RouteReader route = new RouteReader();
read = route.getRoutes();
} catch(IOException iox){
read = new String[1];
read[0] = getResources().getString(R.string.loading_error);
} catch(ArrayIndexOutOfBoundsException aiob){
read = new String[1];
read[0] = getResources().getString(R.string.loading_error);
} catch(NullPointerException npe){
read = new String[1];
read[0] = getResources().getString(R.string.loading_error);
}
return read;
}
#Override
protected void onPostExecute(String[] result) {
values = result;
}
}
This is then called in my onCreate method as new GetRoutes().execute("test");.
However, when I try to run this, my app crashes as a result of a NullPointerException (logcat is available here).
Could you please guide me on how I can fix this?
For further reference, my RouteReader class is as follows:
public class RouteReader extends Reader{
public final static String routeURL =
"http://webservices.nextbus.com/service/publicXMLFeed?command=routeList&a=ttc";
private Map<String, String> routes;
public RouteReader()
throws IOException, ArrayIndexOutOfBoundsException{
super(new URL(routeURL));
routes = xmlToMap();
}
public String[] getRoutes(){
return (String[]) routes.keySet().toArray();
}
public String getRouteNum(String route){
return routes.get(route);
}
private Map<String, String> xmlToMap()
throws IOException, ArrayIndexOutOfBoundsException{
Map<String, String> data = new HashMap<String, String>();
String input;
do{
input = getReader().readLine();
if (input.startsWith("<route")){
String[] read = input.split("\"");
data.put(read[3], read[1]);
}
}while (!input.equals("</body>"));
return data;
}
}
from your log:
Caused by: java.lang.NumberFormatException: Invalid int: "1S"
this is probably caused in this line:
data.put(read[3], Integer.parseInt(read[1]));
We'll your log shows a NumberFormatException at RouteReader lines 35. That's not a NullPointerException - it's a failure to parse a string as an integer, because the string is "1S". You should work out what you want to do with invalid data, and handle it appropriately.
Additionally, you're comparing strings with == instead of equals, which is almost never what you want to do. Personally I wouldn't try to use string operations to parse the XML in the first place: use an XML parser... That's what it's there for. Your current approach is very brittle in the face of seemingly-harmless changes in the XML format.

References in Java constructor

This is the first version of my code :
public class ListSchedule implements ListInterface {
private ArrayList<Schedule> list;
private String cookie;
public ListSchedule() {
this.list = new ArrayList<Schedule>();
}
public ArrayList<Schedule> getList() {
return list;
}
}
In another class, I made this call :
protected final ListSchedule parse(String jsonString)
throws CustomException {
ListSchedule list = new ListSchedule();
JSONArray schedulesArray;
try {
// Convert the response to a JSONObject
JSONObject json = new JSONObject(jsonString);
try {
int errorCode = json.getInt("error");
// Check if there is no error from FilBleu server
if (errorCode > 0) {
throw new CustomException(
CustomException.ERROR_FILBLEU,
"DataAccessObject", "Server error "
+ json.getInt("subError"));
}
try {
String cookie = json.getString("cookie");
list = new ListSchedule(cookie);
} catch (JSONException e) {
throw new CustomException(CustomException.JSON_FORMAT,
"DataAccessObject", "No cookie value");
}
schedulesArray = json.getJSONArray("schedules");
// NullPointerException with the line below
Log.d("DAO", list.getList().toString());
parseSchedulesArray(list, schedulesArray);
} catch (JSONException e) { // Unable to get the error code
throw new CustomException(CustomException.JSON_FORMAT,
"DataAccessObject", "Bad JSON format ("
+ e.getMessage() + ")");
}
} catch (JSONException e) { // Unable to convert response
throw new CustomException(CustomException.JSON_FORMAT,
"DataAccessObject", "Bad JSON format ("
+ e.getMessage() + ")");
}
return list;
}
then I had a NullPointerException from the line Log.d("DAO", list.getList().toString());. So I tried another solution. As you can see, the only difference is the initialization of the list property :
public class ListSchedule implements ListInterface {
private ArrayList<Schedule> list = new ArrayList<Schedule>();
private String cookie;
public ListSchedule() {
}
public ArrayList<Schedule> getList() {
return list;
}
}
and the NullPointerException was never thrown again...
I don't really understand the difference between the two ways of initializing the list property. Can somebody give me a hint please ?
I am speculating that the following constructor exists in your code base :
public ListSchedule(String cookie) {
this.cookie = cookie;
}
and what you need is the following:
public ListSchedule(String cookie) {
this.cookie = cookie;
this.list = new ArrayList<Schedule>();
}
This is further validated by the invocation of this line in your program:
list = new ListSchedule(cookie);
Notice how you don't initialize the list in the second constructor. Also you start by invoking the default constructor, but you later reassign the pointer to the object into what gets created from the String constructor of ListSchedule.
You code is calling this constructor:
list = new ListSchedule(cookie);
Which to me, does not call the one that initializes your ArrayList<Schedule> and that explains the NullReferenceException

Return data from AsyncTask class

How do I get the data from my AsyncTask? My MainActivity is calling the DataCall.getJSON function that triggers the AsyncTask but I am not sure how to get the data back to the original Activity.
MainActivity with call to DataCall that should return a string and save it in state_data
String state_data = DataCall.getJSON(spinnerURL,spinnerContentType);
DataCall:
public class DataCall extends Activity {
private static final String TAG = "MyApp";
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
protected void onPostExecute(String result) {
//THIS IS WHERE I NEED TO RETURN MY DATA TO THE MAIN ACTIVITY. (I am guessing)
}
}
public void getJSON(String myUrlString, String contentType) {
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute(new String[] { "http://www.mywebsite.com/" + myUrlString });
}
}
modify your AsyncTask as below:
public class GetData extends AsyncTask<String, Void, String>
{
DataDownloadListener dataDownloadListener;
public GetData()
{
//Constructor may be parametric
}
public void setDataDownloadListener(DataDownloadListener dataDownloadListener) {
this.dataDownloadListener = dataDownloadListener;
}
#Override
protected Object doInBackground(Object... param)
{
// do your task...
return null;
}
#Override
protected void onPostExecute(Object results)
{
if(results != null)
{
dataDownloadListener.dataDownloadedSuccessfully(results);
}
else
dataDownloadListener.dataDownloadFailed();
}
public static interface DataDownloadListener {
void dataDownloadedSuccessfully(Object data);
void dataDownloadFailed();
}
}
and use it in your Activity
GetData getdata = new GetData();
getdata.setDataDownloadListener(new DataDownloadListener()
{
#SuppressWarnings("unchecked")
#Override
public void dataDownloadedSuccessfully(Object data) {
// handler result
}
#Override
public void dataDownloadFailed() {
// handler failure (e.g network not available etc.)
}
});
getdata.execute("");
NOTE: For the people who are reading this.
Please consider this post for the best and perhaps right implementation.
The key for me was to create a class called URLWithParams or something because AsyncTask will allow only 1 type to be sent IN, and I needed both the URL and the params for the HTTP request.
public class URLWithParams {
public String url;
public List<NameValuePair> nameValuePairs;
public URLWithParams()
{
nameValuePairs = new ArrayList<NameValuePair>();
}
}
and then I send it to a JSONClient:
public class JSONClient extends AsyncTask<URLWithParams, Void, String> {
private final static String TAG = "JSONClient";
ProgressDialog progressDialog ;
GetJSONListener getJSONListener;
public JSONClient(GetJSONListener listener){
this.getJSONListener = listener;
}
#Override
protected String doInBackground(URLWithParams... urls) {
return connect(urls[0].url, urls[0].nameValuePairs);
}
public static String connect(String url, List<NameValuePair> pairs)
{
HttpClient httpclient = new DefaultHttpClient();
if(url == null)
{
Log.d(TAG, "want to connect, but url is null");
}
else
{
Log.d(TAG, "starting connect with url " + url);
}
if(pairs == null)
{
Log.d(TAG, "want to connect, though pairs is null");
}
else
{
Log.d(TAG, "starting connect with this many pairs: " + pairs.size());
for(NameValuePair dog : pairs)
{
Log.d(TAG, "example: " + dog.toString());
}
}
// Execute the request
HttpResponse response;
try {
// Prepare a request object
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(pairs));
response = httpclient.execute(httpPost);
// Examine the response status
Log.i(TAG,response.getStatusLine().toString());
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
String json = reader.readLine();
return json;
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String json ) {
getJSONListener.onRemoteCallComplete(json);
}
public interface GetJSONListener {
public void onRemoteCallComplete(String jsonFromNet);
}
}
Then call it from my main class like this
public class BookCatalog implements GetJSONListener {
private final String TAG = this.getClass().getSimpleName();
private String catalog_url = "URL";
private void getCatalogFromServer() {
URLWithParams mURLWithParams = new URLWithParams();
mURLWithParams.url = catalog_url;
try {
JSONClient asyncPoster = new JSONClient(this);
asyncPoster.execute(mURLWithParams);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onRemoteCallComplete(String jsonBookCatalogList) {
Log.d(TAG, "received json catalog:");
Log.d(TAG, jsonBookCatalogList);
JSONObject bookCatalogResult;
try {
bookCatalogResult = (JSONObject) new JSONTokener(jsonBookCatalogList).nextValue();
JSONArray books = bookCatalogResult.getJSONArray("books");
if(books != null) {
ArrayList<String> newBookOrdering = new ArrayList<String>();
int num_books = books.length();
BookCatalogEntry temp;
DebugLog.d(TAG, "apparently we found " + Integer.toString(num_books) + " books.");
for(int book_id = 0; book_id < num_books; book_id++) {
JSONObject book = books.getJSONObject(book_id);
String title = book.getString("title");
int version = book.getInt("price");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Although i disagree creating a new activity for that simple task there is
startActivityForResult()
to get data from another activity.
Check this. You can store your data to the Intent's extras. But still if you have a large amount of data you better off write it to a file get the result from the other activity that is done downloading and then read the file.
Serialize it and then read it. The only way I'm aware of.
Some options:
a) Make your bean implement Serializable interface, you can then pass your bean through Intent.
b) Implement Application interface (you need to make an entry in manifest), Have setter\getter method in your Application class. You can set your bean in Application from AsyncTask and later retrieve from Activity.
Sorry for answering so late, i think by this time you might have solved this problem. when i was searching for something else, i came across your question. I'm pasting a link here which might of some help for others.

Categories