2

I have a private subclass in my public class. This private class extends AsyncTask. In onPostExecute() , i have to send my List of objects through custom adapter. But the problem is when i get the "context" of main public class(parent of private subclass), it gives an error on @Override (OnPostExecute()).

public class MainListActivity extends ListActivity {

protected String[] mBlogPost;
public static final int NUMBER_OF_POST = 20;
public static final String TAG= MainListActivity.class.getSimpleName();

    public void loadPage() {
    Log.d(TAG,"loadpage me a gae nh");
   // if((sPref.equals(ANY)) && (wifiConnected || mobileConnected)) {
        new DownloadXmlTask().execute(URL);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main_list);
    loadPage();
}
private class DownloadXmlTask extends AsyncTask<String, Void, Object> {
    @Override
    protected Object 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> results) {
        String title,link,summary;
        ArrayList<HashMap<String,String>> blogPosts = new ArrayList<HashMap<String,String>>();
        for(StackOverflowXmlParser.Entry result : results){
            title = result.title;
            link = result.link;
            summary = result.summary;
            HashMap<String,String> blogPost = new HashMap<String,String>();
            blogPost.put("link",link);
            blogPost.put("title",title);
            //blogPost.put("summary",summary);

            blogPosts.add(blogPost);
        }
        String[] keys = {"title","link"};
        int[] ids = {android.R.id.text1,android.R.id.text2};
        SimpleAdapter adapter =
                new SimpleAdapter(MainListActivity.this,blogPosts,android.R.layout.simple_list_item_2,keys,ids);
        setListAdapter(adapter);
    }

It is giving an error on @Override. I have to get the context of parent class of private subclass(this extends asyncTask and have onPostExecute())

I also used getApplicationContext(). Moreover I also made a new public class for context and getting context from there.

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;
        Calendar rightNow = Calendar.getInstance();
        DateFormat formatter = new SimpleDateFormat("MMM dd h:mmaa");


        StringBuilder htmlString = new StringBuilder();

        try {
            stream = downloadUrl(urlString);
            entries = stackOverflowXmlParser.parse(stream);
            // Makes sure that the InputStream is closed after the app is
            // finished using it.
        } finally {
            if (stream != null) {
                stream.close();
            }
        }
        for (StackOverflowXmlParser.Entry entry : entries) {
            htmlString.append("<p><a href='");
            htmlString.append(entry.link);
            htmlString.append("'>" + entry.title + "</a></p>");
            htmlString.append(entry.summary);

        }
        for (StackOverflowXmlParser.Entry entry : entries)
        {
            Log.d(TAG, entry.link + " /" + entry.title);
        }

            //return htmlString.toString();
            return entries;
    }
user3585510
  • 131
  • 2
  • 10

2 Answers2

3
private class DownloadXmlTask extends AsyncTask<String, Void, Object>

In this line you define 3 things.

String the type of the parameter passed to protected Object doInBackground(String... urls). This is correct.

Void the type of the parameter passed to protected void onProgressChanged(Integer... values). You are not using this method so it should be fine.

Object the type of the parameter passed to protected void onPostExecute(List<StackOverflowXmlParser.Entry> results). This is wrong. You need to match these. Either change

protected void onPostExecute(List<StackOverflowXmlParser.Entry> results)

to

protected void onPostExecute(Object results)

or change AsyncTask<String, Void, Object> to

AsyncTask<String, Void, List<StackOverflowXmlParser.Entry>>

Then if you do that, you must also change protected Object doInBackground(String... urls) to match that return type to the type that onPostExecute() expects. What value you are going to return in that method is up to you (it must match the return type though) and I'm not going into detail how to implement that.

Please also refer to the image in this answer: enter image description here

Community
  • 1
  • 1
Tim
  • 41,901
  • 18
  • 127
  • 145
  • Thank you. Just one more thing. If i implemented the second change you suggest in AsyncTask<> , then i should return List from doInBackground. Currently it is returning array of objects. I have to change it to List of object? Just tell me is it right way to go.. Actually i'm a beginner – user3585510 Oct 29 '15 at 13:16
  • 1
    @user3585510 it can be anything. What you return in `doInBackground()` there depends on what you want to receive in the `onPostExecute()`. If you want an object, return an object, if you want something else, return something else. As long as all the signatures match with the definition of the `AsyncTask<..>` – Tim Oct 29 '15 at 13:18
2

Your implementation of AsyncTask is incorrect. You specified the generic types as <String, Void, Object> but your onPostExecute method takes an argument of type List<StackOverflowXmlParser.entry>

Change it to the following

private class DownloadXmlTask extends AsyncTask<String, Void, List<StackOverflowXmlParser.Entry>> {
    private Exception mException = null;
    private Context mContext

    public DownloadXmlTask(Context context) {
        mContext = context;
    }

    @Override
    protected List<StackOverflowXmlParser.Entry> doInBackground(String... urls) {
        try {
            return loadXmlFromNetwork(urls[0]);
        } catch (IOException e) {
            mException = e;
        } catch (XmlPullParserException e) {
            mException = e;
        }

        return null;
    }

    @Override
    protected void onPostExecute(List<StackOverflowXmlParser.Entry> results) {
        if (results != null && mException == null) {
          // Do your stuff
          // Rather use mContext as the context for your SimpleAdapter. Injection is always better.
        } else {
            if (mException instanceof IOException){
              //Handle the IOException seperately
            } else if (mException instanceof XmlPullParserException) {
              //Handle the XmlPullParserException seperately
            }
        }
    }
}

This also gives you the exception when you're in the post execute

the-ginger-geek
  • 7,041
  • 4
  • 27
  • 45
  • It is probably correct, but maybe not, because we don't know what `loadXmlFromNetwork` returns – Tim Oct 29 '15 at 13:13
  • @TimCastelijns true. I just accepted List as the type because it was set as the type for onPostExecute. I would rather not pass Object as a type that can be confused with strings and other types. instanceof everywhere is messy. I only used it for the exception handling to show that you can still handle both in onPostExecute without passing strings – the-ginger-geek Oct 29 '15 at 13:19
  • I know and it makes sense. But it's an assumption so it *might* not work. – Tim Oct 29 '15 at 13:22
  • it is retruning List entries – user3585510 Oct 29 '15 at 13:23
  • I thank both of you to help me as i have solved my question. Big Hug – user3585510 Oct 29 '15 at 13:54