inrob
inrob

Reputation: 5089

Android asynctask, prevent UI from freezing

I have this peace of code, that fetches some xml data from an url.

It does it's job properly but the problem is that while it downloads and parses xml the UI freezes, and that might be a problem for the users.

Here is the class

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.kategoria);

    // getting intent data
    Intent in = getIntent();
    String cat_name = in.getStringExtra("kategoria");
    //Update Textview
    TextView kategoriatw = (TextView)findViewById(R.id.name_of_cat);
    kategoriatw.setText(cat_name);



    // Kategoro URL
    String catUrl = "http://sample.com/xmldata.xml";


    ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>();
    //MOTHERLAJME MULTIDIMENSIONAl
    final List<HashMap<String, String>> MotherContainer= new ArrayList<HashMap<String, String>>();


    try{ 

        XMLParser parser = new XMLParser();
        String xml   = parser.getXmlFromUrl(catUrl); // getting XML
        Document doc = parser.getDomElement(xml); // getting DOM element


        //ALL
        NodeList forecastW = doc.getElementsByTagName("newsitem");

        for (int j = 0; j < forecastW.getLength(); j++)
        {
            HashMap<String, String> map = new HashMap<String, String>();

            Node nodeday = forecastW.item(j);
            Element dayElmnt = (Element) nodeday;

            map.put("title", (parser.getValue(dayElmnt, "title")) );
            map.put("intro", (parser.getValue(dayElmnt, "intro")).toString());

            map.put("story_id", ""+j ); 

            // adding HashList to ArrayList
            menuItems.add(map);


            //MULTI DIMENSIONAL ARRAY
            HashMap<String, String> TheStory= new HashMap<String, String>();
            TheStory .put("title", (parser.getValue(dayElmnt, "title")));
            TheStory .put("story_date", parser.getValue(dayElmnt, "datetime"));
            MotherContainer.add(j, TheStory);
            /////////////////////////

        }


    } catch (Exception e) {
        System.out.println("XML Pasing Excpetion = " + e);
    }



    // Adding menuItems to ListView
    ListAdapter adapter = new SimpleAdapter(this, menuItems,
            R.layout.week_day_item,
            new String[] { "title", "intro", "story_id"}, new int[] {
                    R.id.title_list,
                    R.id.intro_list,
                    R.id.story_id_list});

    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) {

            // Starting new intent
            Intent in = new Intent(getApplicationContext(), SingleLajm.class);
            //start new intent....
            startActivity(in);

        }

    });

}

I want to use Asynctask so that the UI won't freeze and Im using this on my class, this is the "updated" version of the class that Im using, that implements async:

Document doc;
String xml;
ListView lv;
//ListViewAdapter adapter;
//ArrayList<HashMap<String, String>> menuItems;
ProgressDialog pDialog;


final ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>();
//MOTHERLAJME MULTIDIMENSIONAl
final List<HashMap<String, String>> MotherLajme= new ArrayList<HashMap<String, String>>();

final HashMap<String, String> nrLajmit = new HashMap<String, String>();


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.kategoria);

    // getting intent data
    Intent in = getIntent();
    // Get emr
    String catname = in.getStringExtra("kategoria");
    //Textview
    TextView kategoriatw = (TextView)findViewById(R.id.kategoria_emri);
    kategoriatw.setText(catname);



}

private class loadMoreListView extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        // Showing progress dialog before sending http request
        pDialog = new ProgressDialog(
                Kategoria.this);
        pDialog.setMessage("Please wait..");
        pDialog.setIndeterminate(true);
        pDialog.setCancelable(false);
        pDialog.show();
    }

    protected Void doInBackground(Void... unused) {
        new Runnable() {
            public void run() {


                XMLParser parser = new XMLParser();
                String xml   = parser.getXmlFromUrl("http://sample.com/data.xml"); // getting XML
                Document doc = parser.getDomElement(xml); // getting DOM element


                //ALL
                NodeList forecastW = doc.getElementsByTagName("newsitem");

                for (int j = 0; j < forecastW.getLength(); j++)
                {
                    HashMap<String, String> map = new HashMap<String, String>();

                    Node nodeday = forecastW.item(j);
                    Element dayElmnt = (Element) nodeday;

                    map.put("title", (parser.getValue(dayElmnt, "title")) );
                    map.put("intro", (parser.getValue(dayElmnt, "intro")) );

                    map.put("story_id", ""+j ); 
                    // adding HashList to ArrayList
                    menuItems.add(map);


                    //MULTI DIMENSIONAL ARRAY
                    HashMap<String, String> TheLajmi= new HashMap<String, String>();
                    TheLajmi .put("title", (parser.getValue(dayElmnt, "title")));
                    TheLajmi .put("newsdate", parser.getValue(dayElmnt, "datetime"));
                    MotherLajme.add(j, TheLajmi);
                    /////////////////////////

                }


            }
        };

        return (null);
    }


    protected void onPostExecute(Void unused) {
        // closing progress dialog
        pDialog.dismiss();

        // Adding menuItems to ListView
        ListAdapter adapter = new SimpleAdapter(Kategoria.this, menuItems,
                R.layout.week_day_item,
                new String[] { "title", "intro", "story_id"}, new int[] {
                        R.id.title_list,
                        R.id.intro_list,
                        R.id.story_id_list});

        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) {
                // getting values from selected ListItem

                // Starting new intent
                Intent in = new Intent(getApplicationContext(), SingleLajm.class);
                in.putExtra("title", "blabla");
                startActivity(in);

            }

        });

    }
}

But I can't get it to work. All I see is either a blank page or some error that I cannot edit the views.

Can someone help to solve this issue?

Thanks.

Upvotes: 0

Views: 1204

Answers (1)

Shayan Pourvatan
Shayan Pourvatan

Reputation: 11948

try following code:

private class LoadMoreListView extends AsyncTask<Void, Void, ArrayList<HashMap<String, String>>> {

@Override
protected void onPreExecute() {
    // Showing progress dialog before sending http request
    pDialog = new ProgressDialog(
            AndroidListViewWithLoadMoreButtonActivity.this);
    pDialog.setMessage("Please wait..");
    pDialog.setIndeterminate(true);
    pDialog.setCancelable(false);
    pDialog.show();
}

protected ArrayList<HashMap<String, String>> doInBackground(Void... unused) {

      ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>();
//MOTHERLAJME MULTIDIMENSIONAl
final List<HashMap<String, String>> MotherContainer= new ArrayList<HashMap<String, String>>();


try{ 

    XMLParser parser = new XMLParser();
    String xml   = parser.getXmlFromUrl(catUrl); // getting XML
    Document doc = parser.getDomElement(xml); // getting DOM element


    //ALL
    NodeList forecastW = doc.getElementsByTagName("newsitem");

    for (int j = 0; j < forecastW.getLength(); j++)
    {
        HashMap<String, String> map = new HashMap<String, String>();

        Node nodeday = forecastW.item(j);
        Element dayElmnt = (Element) nodeday;

        map.put("title", (parser.getValue(dayElmnt, "title")) );
        map.put("intro", (parser.getValue(dayElmnt, "intro")).toString());

        map.put("story_id", ""+j ); 

        // adding HashList to ArrayList
        menuItems.add(map);


        //MULTI DIMENSIONAL ARRAY
        HashMap<String, String> TheStory= new HashMap<String, String>();
        TheStory .put("title", (parser.getValue(dayElmnt, "title")));
        TheStory .put("story_date", parser.getValue(dayElmnt, "datetime"));
        MotherContainer.add(j, TheStory);
        /////////////////////////

    }


} catch (Exception e) {
    System.out.println("XML Pasing Excpetion = " + e);
}


    return menuItems;
}


protected void onPostExecute(ArrayList<HashMap<String, String>> unused) {
    // closing progress dialog
    pDialog.dismiss();


     // Adding menuItems to ListView
ListAdapter adapter = new SimpleAdapter(YourActivity.this, unused,
        R.layout.week_day_item,
        new String[] { "title", "intro", "story_id"}, new int[] {
                R.id.title_list,
                R.id.intro_list,
                R.id.story_id_list});

setListAdapter(adapter);


}

In AsyncTask

1st param means the type you can pass to execute. Void means you can pass nothing

The class names in Java should start with upper-calse letter. Please rename it for better readability by others.

So proper call would be

new LoadMoreListView().execute();

2nd param is a type of data you can publish calling publishProgress() from doInBackground(). You don't use publishProgress, so nothing to mention in this case.

3rd param mean s type that will be passed to onPostExecute(). To pass the menuItems to onPostExecute you must return it from doInBackground. so you need declare your class with

AsyncTask<Void, Void, ArrayList<HashMap<String, String>>>

doInBackground runs on new thread so you don't need following code:

new Runnable() {
            public void run()

if you want work with UI thread you can use following method:

  1. onPreExecute

  2. onPostExecute

onPreExecute usually used for showing please wait dialog or something like that and onPostExecute used for showing data after downloading and other thing

Upvotes: 5

Related Questions