Question

I'm building an app for my school. I use Android Studio's default Navigation Drawer Fragment and Main Activity for it, and I populate it with fragments according to what the user selects in the drawer.

The problem is that one of my fragments fetches data from the internet, and sets up a List View with it. The List View does not get updated though, and the fragment stays blank. I think it is a matter of updating the UI and I'm not doing it right.

There's the fragment code:

public class NewsFragment extends Fragment {

// ASYNC TASK VARIABLES
NewsAsyncTask crackerTask = new NewsAsyncTask();
String NEWSURL = "http://---.--/H--e.aspx";
String ALERTSURL = "http://---.--/H--e.aspx";
String EVENTSURL = "http://---.--/H--e.aspx";
String string1 = "";
String FINALSTRING = "";

public List<NewsItem> myNews = new ArrayList<NewsItem>();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    //Inflate the layout for this fragment
    return inflater.inflate(R.layout.news_fragment, container, false);

}


@Override
public void onActivityCreated(Bundle savedInstanceState) {
    // INSTANTIATING AND INFLATING THE TABBED LAYOUT
    super.onCreate(savedInstanceState);

    View container = (View) getActivity().findViewById(R.id.news_layout_container) ;

    // ASYNC TASK METHOD EXECUTION UNDER IF STATEMENT
    if (this.isNetworkAvailable()) {

        crackerTask.execute(NEWSURL);
        populateListView();
        registerClickOnListItem();
        // getView().invalidate();

    }
    else{

        Toast.makeText(getActivity(), "No internet connection.",
                Toast.LENGTH_SHORT).show();
    }
}

// CUSTOM METHODS ////////////////////////////////////////////////////
private void actionButtonRefreshPressed() {
    if (this.isNetworkAvailable()) {
        new NewsAsyncTask().execute(NEWSURL); // calling NEW asynctask
        populateListView();
        registerClickOnListItem();

        // because an asynctask
        // can be executed only
        // once.
    }
}

private void populateNewsList(String title, String summary, String date,
                              String link) {
    myNews.add(new NewsItem(title, summary, date, link));

}

private void populateListView() {
    ArrayAdapter<NewsItem> adapter = new MyListAdapter();
    ListView newslist = (ListView) getView().findViewById(R.id.newsListView);
    newslist.setAdapter(adapter);
}

private void registerClickOnListItem() {
    ListView list = (ListView) getView().findViewById(R.id.newsListView);
    list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View viewClicked,
                                int position, long id) {
            // shows toast with info
            NewsItem clickedNewsItem = myNews.get(position);
            String message = "You clicked position " + position
                    + " Which is " + clickedNewsItem.title;
            Toast.makeText(getActivity(), message,
                    Toast.LENGTH_SHORT).show(); // .show is important!
            // otherwise it won't show.
        }
    });
}

private boolean isNetworkAvailable() {
    ConnectivityManager connectivityManager = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager
            .getActiveNetworkInfo();
    return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

// CUSTOM MINI CLASSES /////////////////////////////////////////////////
private class NewsAsyncTask extends AsyncTask<String, String, String> {
    // Genetics of an AsyncTask:
    // 1. Type of reference(s) passed to doInBackground()
    // 2. Type of reference passed to onProgressUpdate()
    // 3. Type of reference returned by doInBackground(). Value passed to
    // onPostExecute()
    ProgressDialog dialog1;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        dialog1 = ProgressDialog.show(getActivity(), "Loading",
                "Fetching data from web...");
    }

    @Override
    protected String doInBackground(String... arguments) {
        // extract arguments
        String newsurl = arguments[0];
        //
        Document root = null;

        try {
            root = Jsoup.connect(newsurl).get();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
        if (root != null) {

            Elements myElements = root.getElementsByClass("news_list")
                    .first().getElementsByTag("table");

            for (Element el : myElements) {
                Element title = el.getElementsByClass("home_title").first();
                Element date = el.getElementsByClass("home_date").first();
                Element link = el.getElementsByClass("news_list_image")
                        .first();
                Element summary = el.getElementsByClass("summary").first();

                populateNewsList(title.text(), summary.text(), date.text(),
                        link.child(0).attr("href"));

            }

            Log.i("ELEMENTS HTML", string1);

        } else {
            string1 = "FAILED TO LOAD";
        }
        return string1;

    }

    @Override
    protected void onPostExecute(String string1) {
        // super.onPostExecute(result);
        if (string1.equals("FAILED TO LOAD")) {
          //  tv2.setText("Failed to load. Check your internet connection.");
            if (dialog1 != null) {
                if (dialog1.isShowing()) {
                    dialog1.dismiss();
                }
            }
            Toast.makeText(getActivity(),
                    "No web connectivity. Try again later.",
                    Toast.LENGTH_LONG).show();

        }else{
           //presumably the download worked so update adapter
          ListView newslist = (ListView) getView().findViewById(R.id.newsListView);
          ((ArrayAdapter)newsList.getAdapter()).notifyDataSetChanged();

        }
        FINALSTRING = string1;
       // tv2.setText(FINALSTRING);
        if (dialog1 != null) {
            if (dialog1.isShowing()) {
                dialog1.dismiss();
            }
        }
    }

}

private class MyListAdapter extends ArrayAdapter<NewsItem> {
    public MyListAdapter() {
        super(getActivity(), R.layout.news_item, myNews);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // make sure we have a view to work with in the lines below, may be
        // given null
        View newsItem = convertView;
        if (newsItem == null) {
            newsItem = getActivity().getLayoutInflater().inflate(R.layout.news_item,
                    parent, false);
        }

        // find the NewsItem we have to work with.
        NewsItem currentNews = myNews.get(position);
        // fill the view.
        ImageView imageView = (ImageView) newsItem
                .findViewById(R.id.newsitem_icon);
        imageView.setImageResource(R.drawable.test_icon); // THIS IS GOING
        // TO BE CHANGED
        // SO IT DOESN'T
        // USE THE
        // DRAWABLE
        // Summary
        TextView summaryText = (TextView) newsItem
                .findViewById(R.id.newsitem_summary);
        summaryText.setText(currentNews.getSummary());
        // Date
        TextView dateText = (TextView) newsItem
                .findViewById(R.id.newsitem_date);
        dateText.setText(currentNews.getDate());
        // Title
        TextView titleText = (TextView) newsItem
                .findViewById(R.id.newsitem_title);
        titleText.setText(currentNews.getTitle());
        return newsItem;
    }
}
}

There are some stuff left from when I was debugging the code, sorry (it was originally in an activity and it worked, the problem occurred when I transferred everything in a fragment).

EDIT: Since I tried so many variants, I suppose the error is that the list view I'm trying to show is empty. I tried putting Log.i("TAG", myNews.get(0).title); in the place of the invalidate(); and it returns an index out of bounds exception. I cannot find the source of the mistake though.

Was it helpful?

Solution

You should be probably be calling notifyDataSetChanged on your adapter (not the listview). Call this in your AsyncTask in post execute.

OTHER TIPS

You are invalidating your view:getView().invalidate(); Time to call requestLayout().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top