【问题标题】:How to update listview from AsyncTask如何从 AsyncTask 更新列表视图
【发布时间】:2014-09-01 17:00:45
【问题描述】:

首先抱歉,如果它是重复的,因为我问它是因为无法理解其他问题的任何内容,或者我可以说我无法在我的情况下实施它。 实际上,我遇到了一种情况,我想用AsyncTask 中的网络更新我的ListView,但现在如何实现它,不知道我尝试了一些东西但无法使其工作。请任何人详细解释我如何做到这一点,这是我的活动代码和异步类

    package app.balaji.sid.listapp;

    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.support.v7.app.ActionBarActivity;
    import android.util.Log;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;

    import it.sauronsoftware.ftp4j.FTPClient;
    import it.sauronsoftware.ftp4j.FTPFile;


    public class ListActivity extends ActionBarActivity {
        ListView lv;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_list);
            lv=(ListView)findViewById(R.id.listView);
            String[] values = new String[] { "Item 1",
                    "Item 2",
                    "Item 3 ",
                    "Item 4",
                    "Item 5",
                    "Item 6",
                    "Item 7",
                    "Item 8"
            };
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                    android.R.layout.simple_list_item_1, android.R.id.text1, values);
            lv.setAdapter(adapter);
            new ListFetcher().execute();


        }


        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.list, menu);
            return true;
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }

        protected class ListFetcher extends AsyncTask<String,String,String>{
            String sid;


            @Override
            protected String doInBackground(String... params) {
                String user = "user";
                String pass="password";
                String host="204.236.238.164";

                FTPClient client = new FTPClient();

                try {

                    client.connect(host,21);
                    client.login(user, pass);
                    client.setType(FTPClient.TYPE_BINARY);
                    client.changeDirectory("/");

                    FTPFile[] files = client.list();
                    String[] fileNames = new String[files.length];

                    for (int i = 0; i < files.length; i++)
                    {
                        fileNames[i] = files[i].getName();
                        String logVariable=fileNames[i];
                        Log.v(sid, logVariable);     // Here i am able to see list in log
                    }

                   }catch (Exception e)
                {

                    Log.v(sid,e.toString());
                }





                return sid;
            }

            protected void onPostExecute()
            {

    //i think list should be updated from here but don't know how to do it correctly
    // i just know i can update my listview by creating a new adapter and assign it to listview but don't know how
// also i am not able to get the fileNames array here

            }



        }
    }

【问题讨论】:

  • A:创建一个继承类,继承 AsyncTask 并让它实现一个 MainActivity 也实现的接口,并在发布时调用它。 B:在您的派生中提供对 Activity 的弱引用并将 Activity 引用传递给派生,以便调用 Activity 的公共方法或从 onPostExecute 调用 runOnUiThread。我认为 onPost 已经在 ui 线程上运行了。
  • @icbytes 能否请您举个例子回答一下,因为我是 android 新手,所以不太了解
  • @icbytes 它确实在 UI 线程上运行,因此不需要 runOnUiThread() 那里

标签: java android listview android-asynctask


【解决方案1】:

如果您发布了指向您尝试过的受骗者的链接并解释您不理解的内容,那么回答会更容易。发生/未发生的事情也会有所帮助。但是,据我所知,您只需将新的String 传递给onPostExecute() 并更新列表和Adapter

protected void onPostExecute(String result)  // get the String you are passing
{

    //i think list should be updated from here but don't know how to do it correctly
    // I agree. Let's try this
    if(result != null)  // let's make sure you got something
    {
         values.add(result);  // add the new String to your list
         adapter.notifyDataSetChanged();  // Hey, Adapter, we've got some new data

}

您需要将Array 更改为ArrayList,以便长度可以是动态的。您还需要创建它和您的 Adapter 成员变量,以便内部类可以看到它们。

public class ListActivity extends ActionBarActivity {
    ListView lv;

    // Declare them here
    ArrayAdapter<String> adapter;
    ArrayList<String> values = new ArrayList<String>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list);
    lv=(ListView)findViewById(R.id.listView);
    values.add("Item 1");
    values.add("Items 2");

    adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
            android.R.id.text1, values);
    lv.setAdapter(adapter);
    new ListFetcher().execute();

你没有向你的任务传递任何东西,但你想返回一个数组

 @Override
        protected String[] doInBackground(Void... params) {

 protected void onPostExecute(String[] result)

如果您要为适配器返回一组全新的值,那么您可以使用新值对其进行更新。如果您只是添加一些值,那么您可以遍历它们并将它们添加到您的 ArrayList 并调用 notifyDataSetChanged(),如上所示。

【讨论】:

  • 感谢您让我了解它,但知道应用程序正在强制关闭 Collections.addAll(values, result); // Log.v(sid,"在这里工作");适配器.notifyDataSetChanged(); // 这里停止
  • 不客气。这比我只给你工作代码更有帮助。我不知道你得到了什么错误。
  • 这是我停止应用程序 09-02 00:05:08.221 4074-4074/app.balaji.sid.listapp E/AndroidRuntime: FATAL EXCEPTION: main Process: app. balaji.sid.listapp, PID: 4074 java.lang.NullPointerException at app.balaji.sid.listapp.ListActivity$ListFetcher.onPostExecute(ListActivity.java:116) at app.balaji.sid.listapp.ListActivity$ListFetcher.onPostExecute( ListActivity.java:61)
  • 第 116 行是null
  • 第116行是adapter.notifyDataSetChanged();,那现在怎么办??
【解决方案2】:

我刚刚解决了我的问题,所以只是想我需要分享一下,这样其他面临同样问题的人可以轻松完成。

所以首先在我的问题中,我刚刚用字符串参数声明了我的 AsyncTask 类,但实际上我需要从这里填充我的 ListView。

所以我做了什么:

 protected class ListFetcher extends AsyncTask<ArrayList,ArrayList,ArrayList>{
        String sid;
        ArrayList list;



        @Override
        protected ArrayList doInBackground(ArrayList... params) {
 FTPClient client = new FTPClient();

            try {

                client.connect(host,21);
                client.login(user, pass);
                client.setType(FTPClient.TYPE_BINARY);
                client.changeDirectory("/");

                FTPFile[] files = client.list();
                String[] fileNames = new String[files.length];

                for (int i = 0; i < files.length; i++)
                {
                    fileNames[i] = files[i].getName();
 String logVariable=fileNames[i];
                    Log.v(sid, logVariable);
                    values.add(fileNames[i]);

                }

               }catch (Exception e)
            {

                Log.v(sid,e.toString());
            }





            return list;
        }

        protected void onPostExecute(final ArrayList  result)//received result but didn't use it because in my case i don't need it instead of it i just updated my arraylist in doInbackground and updated my ui from here
        {


            adapter = new ArrayAdapter<String>(ListActivity.this, android.R.layout.simple_list_item_1, android.R.id.text1, values);
            ListView listView =(ListView)findViewById(R.id.listView);

            listView.setAdapter(adapter);




        }

【讨论】:

  • 如果您在此处设置Adapter,则无需致电notifyDataSetChanged()。那是因为您已经在 ListView 上设置了它并更新了列表。
猜你喜欢
  • 2019-05-25
  • 2019-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-30
  • 1970-01-01
相关资源
最近更新 更多