Search code examples
androidrestandroid-fragmentsandroid-asynctaskandroidhttpclient

Getting the calling fragment within an asynchronous task


Aim

In a fragment, I have a search bar which looks for online news about what the user typed. I would want to display these news (title + description + date of publication + ... etc.) in the GUI, as vertical blocks.

Implementation

Explanations

In the fragment, within the search event handling, I instanciated an asynchronous task and execute it with the good URL REST API I use to do the search.

In the asynchronous task, I make use of this REST API (thanks to the URL and some required parameters as an authorization key, etc.). When my asynchronous task gets answered, it must update the fragment's GUI (i.e.: it must vertically stack GUI blocks containing the titles, descriptions, etc. of the got news).

Sources

You will find sources in the last part of this question.

My question

In the asynchronous task (more precisely: in its function that is executed after having got the answer), I don't know how to get the calling fragment. How to do this?

Sources

Fragment part

private void getAndDisplayNewsForThisKeywords(CharSequence keywords) {
    keywords = Normalizer.normalize(keywords, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "");
    new NetworkUseWorldNews().execute("https://api.currentsapi.services/v1/search?keyword=" + keywords + "&language=en&country=US");
}

Asynchronous task part

    public class NetworkUseWorldNews extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String[] urls) {
            StringBuilder string_builder = new StringBuilder();

            try {
                URL url = new URL(urls[0]);
                HttpsURLConnection https_url_connection = (HttpsURLConnection) url.openConnection();
                https_url

_connection.setRequestMethod("GET");
            https_url_connection.setDoOutput(false);
            https_url_connection.setUseCaches(false);
            https_url_connection.addRequestProperty("Authorization", "XXX");

            InputStream input_stream = https_url_connection.getInputStream();
            BufferedReader buffered_reader = new BufferedReader(new InputStreamReader(input_stream));
            String line;
            while((line = buffered_reader.readLine()) != null) {
                string_builder.append(line);
            }
            buffered_reader.close();

        } catch (IOException e) {
            e.printStackTrace();
        }

        return string_builder.toString();
    }

    @Override
    protected void onPostExecute(String result) {
        try {
            JSONObject news_response_http_call = new JSONObject(result);

            switch(news_response_http_call.getString("status")) {
                case "ok":
                    JSONArray news = news_response_http_call.getJSONArray("news");
                    for(int i = 0; i < news.length(); i++) {
                        JSONObject a_news = news.getJSONObject(i);
                        String title = a_news.getString("title");
                        String description = a_news.getString("description");
                        String date_of_publication = a_news.getString("published");
                        String url = a_news.getString("url");
                        String image = a_news.getString("image");
                        System.out.println(title + ": " + date_of_publication + "\n" + image + "\n" + url + "\n" + description);

                        WorldNewsFragment world_news_fragment = ...;
                    }
                    break;
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

Solution

  • If I am right, you want to update View of your caller Fragment. if FragmentA called service then FragmentA should be update.

    However the approach you are asking is wrong. Instead of getting caller Fragment in your AsyncTask response. You should do it with Callback.

    So now you will need to pass callback in AsyncTask. So instead of posting full code, here are already answers with this problem.

    Finally your calling syntax will look like.

    NetworkUseWorldNews task = new NetworkUseWorldNews(new OnResponseListener() {
        @Override
        public void onResponse(String result) {
            // Either get raw response, or get response model 
        }
    });
    
    task.execute();
    

    Actually I am still very unclear about your question. Let me know in comments if you have more queries.

    Must checkout

    • Retrofit or Volley for calling Rest APIs
    • Gson for parsing JSON response automatically to models