无法在onPostExecute中更新android listview

时间:2014-02-09 12:04:08

标签: java android android-asynctask android-activity

我的onCreate方法中有这个:

String[] myStringArray = {"a","b","c","a","b","c","a","b","c","a","b","c","a","b","c","a","b","c"};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_top_jokes);        

    new loadJson().execute();

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

    ListView listView = (ListView) findViewById(R.id.topJokesList);
    listView.setAdapter(adapter);

    listView.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
            // When clicked, show a toast with the TextView text
            Toast.makeText(getApplicationContext(),
            ((TextView) view).getText(), Toast.LENGTH_SHORT).show();
        }
    });

}

上面的代码填充了一个内容为myStringArray的listView,现在一切正常。当我调用new loadJson().execute();它执行正常时,问题出现了,这是方法的代码:

public class loadJson extends AsyncTask<Void, Integer, String>{

@Override
protected String doInBackground(Void... params) {
    URL u;
    StringBuffer buffer = new StringBuffer();
    try {
    u = new URL("https://website.com/content/showContent.php");
    URLConnection conn = u.openConnection();
    BufferedReader in = new BufferedReader(
                            new InputStreamReader(
                                conn.getInputStream()));

    String inputLine;
    while ((inputLine = in.readLine()) != null) 
        buffer.append(inputLine);
    in.close();

    }catch(Exception e){
        e.printStackTrace();
    }
    return buffer.toString();
}

protected void onPostExecute(String buffer) {
    JSONArray jsonArray = new JSONArray();
    try {
        jsonArray = new JSONArray(buffer);
    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println("JSONarray: " + jsonArray);
    String[] newArray = null;
    for (int i = 0; i < jsonArray.length(); i++) {
        try {

        newArray[i] = jsonArray.getJSONObject(i).toString();
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    myStringArray = newArray;
 }

}

正如您所看到的,我正在使用提取到myStringArray的新值更新newArray的硬编码内容。现在我无法看到新内容。我知道它在那里,但我怎么能告诉当前的活动:“嘿,我更新你的阵列,请显示它!” ?

我知道我错过了一些非常小的东西,但作为初学者,我无法发现它。

9 个答案:

答案 0 :(得分:2)

您切换了数组的引用,您应该在适配器实例上使用clearaddAll(将适配器实例传递给AsyncTask以访问它)。

答案 1 :(得分:2)

在您的onPostExecute中,您可以尝试以下操作:

ListView listView = (ListView) findViewById(R.id.topJokesList);
listView.getAdapter().notifyDataSetChanged();

答案 2 :(得分:2)

protected void onPostExecute(String buffer) {
JSONArray jsonArray = new JSONArray();
try {
    jsonArray = new JSONArray(buffer);
} catch (JSONException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
System.out.println("JSONarray: " + jsonArray);
String[] newArray = null;
for (int i = 0; i < jsonArray.length(); i++) {
    try {

    newArray[i] = jsonArray.getJSONObject(i).toString();
    } catch (JSONException e) {
        e.printStackTrace();
    }
}
myStringArray = newArray;

}

在上面的代码中,您正在使用一些实际驻留在工作线程(doInBackgroud())方法中的代码,因此请将此代码剪切并粘贴到doInBackgound方法中。 然后将此代码保存在onPostExecute方法中,并在oncreate方法之前声明listview和arrayadapter,即Global

listView = (ListView) findViewById(R.id.topJokesList);
listView.getAdapter().notifyDataSetChanged();

我希望这会对你有帮助......

答案 3 :(得分:2)

我找到了这个问题的答案,因为我自己正在寻找答案。 这里有一些接近的答案,但是他们遗漏了一些永远不会让你得到答案的作品。

首先将两个成员变量添加到AsyncTask类中:

private ListView listView;
private Activity activity;

接下来,向AsyncTask类添加一个构造函数,该类接受一个Activity:

  public loadJson(Activity activity) {
        this.activity = activity;
    }

现在,当你新建AsyncTask类并调用execute()时,你将添加对调用它的Activity的引用(在构造AsyncTask类时传入的 this 值)。 / p>

new loadJson(this).execute(param);

最后,回到你的AsyncTask中,你将编写postExecute()的代码,如下所示:

protected void onPostExecute(String output) {
        listView = (ListView) activity.findViewById(R.id.targetListView);
        ArrayAdapter<String> adapter = (ArrayAdapter<String>)listView.getAdapter();
        adapter.add(output);
        adapter.notifyDataSetChanged();
    }

您必须引用您的Activity才能调用findViewById。 请注意,targetListView是ListView的id,它位于原始Activity上。

我们已将该Activity发送到AsyncTask的构造函数中,因此它可用。 现在您可以获取适配器并将值添加到您并调用notifyDataSetChanged(),以便它在您的UI上更新。

我在我的解决方案中使用此代码,效果很好。

答案 4 :(得分:1)

在更新数组列表内容之后,您可以从数组切换到ArrayList并调用adapter.notifyDataSetChanged(但是不要创建新的ArrayList实例,update必须与提供给ArrayAdapter的引用相同)。

或者在AsyncTask.onPostExecute中重复以下代码(来自onCreate):

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

答案 5 :(得分:0)

你需要: A.使用Strings.xml文件 B.将字符串从一个更改为另一个 - 例如

<string name="example1">hi</string>
<string name="example2">hello</string>
在strings.xml文件中

然后在Main类中:

label.setText("@string/example2");

当字符串是example1时。 如果这没有帮助,我不知道会发生什么......

答案 6 :(得分:0)

您可以在asynctask构造函数中添加适配器:

在您的活动中:

    LoadJson lj = new Json(adapter);
    lj.execute();

您可以在LoadJson中声明:

private  ArrayAdapter<String> mAdapter;

在构造函数中,您从活动中获取适配器:

public LoadJson(ArrayAdapter<String> adapter){
      mAdapter = adapter;
}

因此在postExecute中,您可以更新适配器。 希望能帮助到你!

答案 7 :(得分:0)

把&#34; loadJson&#34; class作为ListActivity类的子类(或Activity或您使用的任何活动)

答案 8 :(得分:0)

只需将Adapter的引用添加到AsyncTask:

public class loadJson extends AsyncTask<Void, Integer, String>{

    ArrayAdapter<String> adapter;

    public loadJson(ArrayAdapter<String> adapter) {
        this.adapter = adapter;
    }

    //...

    protected void onPostExecute(String buffer) {
        if (this.adapter != null) {
            // update adapter
        }
    }

}

然后

new loadJson(adapter).execute();  

现在,您可以在Adapter

中更新onPostExecute