【问题标题】:Android asynctask, prevent UI from freezingAndroid asynctask,防止UI冻结
【发布时间】:2014-03-23 19:08:45
【问题描述】:

我有这样的代码,它从 url 获取一些 xml 数据。

它可以正常工作,但问题是在下载时 并解析 UI 冻结的 xml,这对用户来说可能是个问题。

这是课程

    @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);

        }

    });

}

我想使用 Asynctask,这样 UI 就不会冻结,我在课堂上使用它, 这是我使用的类的“更新”版本,它实现了异步:

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

            }

        });

    }
}

但我无法让它工作。我看到的只是空白页或一些错误 我无法编辑视图。

有人可以帮忙解决这个问题吗?

谢谢。

【问题讨论】:

  • 我认为您需要再次阅读asynctask 的文档,为什么您在doInBackground 中使用runOnUiThread?删除它,我认为您的问题将得到解决,并将所有 UI 代码放入 onPostExecute
  • 你在onCreate() 中做了几乎所有事情。所有这些“几乎所有内容”ᵀᴹ 必须在您的 UI 显示之前完成。
  • 是的,我知道这一点。这就是我想使用 asynctask 的原因
  • @bornie 你的问题解决了吗?你删除了runOnUiThread吗?
  • 那么您还需要将所有列表初始化和 XML 解析移出那里。

标签: android xml android-listview android-asynctask


【解决方案1】:

试试下面的代码:

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


}

AsyncTask

第一个参数表示您可以传递执行的类型。无效意味着你什么都不能通过

Java 中的类名应以大写字母开头。请重命名它以便其他人更好地阅读。

所以正确的调用是

new LoadMoreListView().execute();

第二个参数是一种数据类型,您可以从doInBackground() 调用publishProgress() 发布。你没有使用publishProgress,所以在这种情况下没什么好说的。

第三个参数表示将传递给onPostExecute() 的类型。要将 menuItems 传递给 onPostExecute,您必须从 doInBackground 返回它。所以你需要用

声明你的类
AsyncTask<Void, Void, ArrayList<HashMap<String, String>>>

doInBackground 在新线程上运行,因此您不需要以下代码:

new Runnable() {
            public void run()

如果您想使用 UI 线程,您可以使用以下方法:

  1. onPreExecute

  2. onPostExecute

onPreExecute 通常用于显示请等待对话框或类似的东西,onPostExecute 用于显示下载后的数据等

【讨论】:

  • 谢谢,但我收到一个错误 - 返回类型与 AsyncTask.doInBackground(Void[]) 不兼容
  • AsyncTask&lt;Void,Void,ArrayList&lt;HashMap&lt;String, String&gt;&gt;&gt;改变它
  • - 返回类型不兼容 AsyncTask.doInBackground(Void[]) - 实现 android.os.AsyncTask.doInBackground
  • 我认为您没有看到我的评论,我编辑了我的帖子并将该行添加到第一行代码中,看到了
  • @shayanpourvatan,非常感谢我的朋友。我感谢您的帮助! :)
猜你喜欢
  • 2021-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-12
相关资源
最近更新 更多