ASyncTask 并返回一个 ArrayList

ASyncTask and returning an ArrayList

我正在尝试 return 从 AsyncTask class 返回 MainAcitivity class 的 ArrayList,然后使用此 arraylist 填充 MainActivity 中的 gridview。

parseURL 采用字符串参数来解析 url。当用户单击按钮时执行 parseURL。我编译的代码 运行 但在触发按钮事件 并按下按钮两次后应用程序崩溃后 gridview 未填充。

编辑:添加循环回调后,它停止崩溃,但它仍然不会填充 gridview。 我要填充 gridview 的 ArrayList 对象采用这种格式 10,John,Smith

这是我的 MainActivity 代码(使用 Stanislav Bodnar 建议)

private GridView grid1;
private ArrayAdapter<String> adapter;

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //initalized the grid and adapter
    grid1 = (GridView)findViewById(R.id.gridView1);

    adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
    grid1.setAdapter(adapter);
 }

public void onButtonClick(View v) {
EditText textInput = (EditText) findViewById(R.id.editText1);
String code = textInput.getText().toString();

new parseURL() {
    @Override
    protected void onPostExecute(List<String> list) {
        //use the list from parseURL to fill grid view
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);

        gridView.setAdapter(adapter);
        adapter.notifyDataSetChanged();
    }
}.execute(code);

解析网址 class

public class parseURL extends AsyncTask<String, Void, List<String>> {

protected List<String> doInBackground(String... params) {
    List<String> str = new ArrayList<String>();
    try {
        Document doc = Jsoup.connect("http://www.mywebsite.com/id/" + params).get();

        Elements row1 = doc.select("table");
        Elements row2 = doc.select("td");
        Elements row3 = doc.select("td");

        for (int i = 0; i < row1.size(); i++) {
            str.add(row1.get(i).text() + "," + row2.get(i).text() + "," + row2.get(i).text());
        }
        return str;
    } catch (Exception e) {
        return new ArrayList<String>();
    }
}

A​​syncTask 根据定义是异步的。您的代码处理它就像它是同步的。

移动

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);

gridView.setAdapter(adapter);
adapter.notifyDataSetChanged();

进入setList方法。

此外,绕过 MainActivity 感觉有点不稳定。如果 Activity 在异步任务期间被销毁会怎样? 相反,将 AsyncTask 设为私有内部 class 或 MainActivity

中的匿名 class

当然,您需要在填充列表之前对其进行初始化。

您可以添加加载回调。

public void onButtonClick(View v) {
    EditText textInput = (EditText) findViewById(R.id.editText1);
    String code = textInput.getText().toString();

    new parseURL() {
        @Override
        protected void onPostExecute(List<String> list) {
            //use the list from parseURL to fill grid view
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);

            gridView.setAdapter(adapter);
            adapter.notifyDataSetChanged();
        }
    }.execute(code);
}

异步任务:

public class parseURL extends AsyncTask<String, Void, List<String>> {

    protected List<String> doInBackground(String... params) {
        List<String> str = new ArrayList<String>();
        try {
            Document doc = Jsoup.connect("http://www.mywebsite.com/id/" + params).get();

            Elements row1 = doc.select("table");
            Elements row2 = doc.select("td");
            Elements row3 = doc.select("td");

            for (int i = 0; i < row1.size(); i++) {
                str.add(row1.get(i).text() + "," + row2.get(i).text() + "," + row2.get(i).text());
            }
            return str;
        } catch (Exception e) {
            return new ArrayList<String>();
        }
    }
}

补充

如果 returns by onPostExecute 的数组列表不为空,您的网格将以接下来的方式填充,每个单元格将包含字符串 10,John,Smith。请检查 doInBackground 方法是否未捕获某些异常并正确填充数组列表。

接下来,如果您想创建一个 table 视图,其中 1 行将包含 3 列 10 |约翰 | Smith 然后将数据解析成对象结构:

class Person {
    private int id;
    private String firstName;
    private String lastName;
}

然后将方法 doInBackground 更改为 return Person 对象的数组列表。

创建自定义适配器(扩展 BaseAdapter),其中初始化视图使用 Person 对象。 视图将作为水平方向的 LinearLayout,其中将包含 3 个具有布局权重的 TextView(android:layout_weight="0.3" - 在每个 TextView 中设置,您可以更改此值)。然后使用 ListView 而不是 GridView。列表视图的每一行将包含 1 个人。

不要 gridview.setAdapter() 两次。该代码存在一些问题。正如 P-a Bäckström 所写:

Also, passing around the MainActivity feels a bit shaky. What happens if the Activity is destroyed during the async-task? Instead, make the AsyncTask a private inner class or an anonymous class in MainActivity

你也需要解决这个问题。现在是更新部分:

像这样声明一个全局处理程序:

private final Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        if(msg.what == 1) {
            List<String> list = (List) msg.obj;
            adapter.insert(list);
            adapter.notifyDataSetChanged();
        }
    }
};

然后在 onPostExecute() 中使用处理程序将您的数据发送到 UI 线程并更新 gridview:

protected void onPostExecute(List<String> list) {
    handler.obtainMessage(1, list);
}

试试这个:

Mainactivity.class

private GridView grid1;
private ArrayAdapter<String> adapter;

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //initalized the grid and adapter
    grid1 = (GridView)findViewById(R.id.gridView1);

    adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
    grid1.setAdapter(adapter);
 }

public void onButtonClick(View v) {
    EditText textInput = (EditText) findViewById(R.id.editText1);
    String code = textInput.getText().toString();
    new parseURL(this).execute(code);
}

public void onBackgroundTaskCompleted(List<String> result) {
    // TODO Auto-generated method stub
    Log.i(TAG, "onBackgroundTaskCompleted List: "+result);

    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);

    gridView.setAdapter(adapter);
    adapter.notifyDataSetChanged();
}

异步任务:

public class parseURL extends AsyncTask<String, Void, List<String>> {

MainActivity caller;

    public Scheduler(MainActivity mainActivity) {
        // TODO Auto-generated constructor stub
        this.caller = mainActivity;
    }
    protected void onPostExecute(List<String> result) {
            caller.onBackgroundTaskCompleted(result);
    }

    protected List<String> doInBackground(String... params) {
        List<String> str = new ArrayList<String>();
        try {
            Document doc = Jsoup.connect("http://www.mywebsite.com/id/" + params).get();

            Elements row1 = doc.select("table");
            Elements row2 = doc.select("td");
            Elements row3 = doc.select("td");

            for (int i = 0; i < row1.size(); i++) {
                str.add(row1.get(i).text() + "," + row2.get(i).text() + "," + row2.get(i).text());
            }
            return str;
        } catch (Exception e) {
            return new ArrayList<String>();
        }
    }
}