无法在onPostExecute中更新android列表视图

4
我在我的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;
 }

}

你可以看到我正在使用newArray中获取的新值来更新myStringArray中的硬编码内容。现在我无法看到新的内容。我知道它们在那里,但是如何告诉当前的活动:“嘿,我已经更新了你的数组,请显示它!”?

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


1
你在哪里调用了adapter.notifyDataSetChanged(); - ρяσѕρєя K
我无法在onPostExecute中访问adapter - chility
1
为什么你不能将适配器实例声明为全局变量,并在onCreate方法中初始化,然后就可以在整个类中访问,包括内部类。 - ρяσѕρєя K
我做不到 :( - chility
9个回答

3
我发现这个问题的答案是因为我自己在寻找答案。 这里有一些接近答案的回答,但它们遗漏了一些部分,这些部分将永远无法让你得到答案。
首先,在您的AsyncTask类中添加两个成员变量:
private ListView listView;
private Activity activity;

接下来,向您的AsyncTask类添加一个构造函数,该构造函数需要接受一个Activity参数:
  public loadJson(Activity activity) {
        this.activity = activity;
    }

现在,当您新建一个AsyncTask类并调用execute()时,您将添加对调用它的Activity的引用(在构造AsyncTask类时传递的this值)。
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();
    }

您需要引用活动,以便可以调用findViewById方法。 请注意,targetListView是原始Activity上的ListView的ID。

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

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


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

但是我无法在onPostExecute中访问adapter - chility
3
如果你正在编写代码,就没有“我不会”的说法,只需在创建任务时将其作为参数传递即可。 - shem
我喜欢这种精神,但在安卓世界中我无能为力。感谢您的帮助! - chility

2
在你的onPostExecute中,你可以尝试以下操作:
ListView listView = (ListView) findViewById(R.id.topJokesList);
listView.getAdapter().notifyDataSetChanged();

我对此没有运气 :( - chility
1
我认为还有另一个问题:你没有初始化你的newArray吧?例如,代码行 String[] newArray = null; 应该接着写 newArray = new String[jsonArray.length()]; - jzyamateur

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())方法中,因此请将此代码剪切并粘贴到doInBackground方法中。 然后将此代码保留在onPostExecute方法中,并在onCreate方法之前声明listview和arrayadapter,即全局范围内。
listView = (ListView) findViewById(R.id.topJokesList);
listView.getAdapter().notifyDataSetChanged();

希望这能对你有所帮助...


如何使它们全局?我已经尝试了一切让它工作。 :( - chility

1
你可以从数组切换到ArrayList,然后调用adapter.notifyDataSetChanged,在更新ArrayList内容后(但不要创建新的ArrayList实例,更新必须在提供给ArrayAdapter的相同引用上进行)。
或者在你的AsyncTask.onPostExecute中重复以下代码(来自onCreate):
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
        android.R.layout.simple_list_item_1, newArray);
listView.setAdapter(adapter);

当我将它放在 onPostExecute 中时,我收到了这个错误:The constructor ArrayAdapter<String>(TopJokes.loadJson, int, String[]) is undefined - chility
将“this”更改为“MyActivity.this”。 - marcinj
我的应用程序在更改后刚刚崩溃了 :( - chility
查看logcat,同时您没有分配newArray,还将结果存储在newJokes中。 - marcinj
Log cat 抛出了一堆错误,newArray 已经修复了,但问题仍然存在。我想我已经对 Android 无能为力了。感谢你的帮助! - chility

0

只需将适配器的引用添加到您的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();  

现在你可以在onPostExecute中更新你的Adapter


0

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

在你的活动中:

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

你可以在LoadJson中声明:

private  ArrayAdapter<String> mAdapter;

在构造函数中,您可以从活动中获取适配器:
public LoadJson(ArrayAdapter<String> adapter){
      mAdapter = adapter;
}

在你的postExecute中,你可以更新适配器。 希望能帮到你!

0
将“loadJson”类作为您的ListActivity类(或Activity或您使用的任何活动)的子类。

这实际上是一个糟糕的建议。你必须防止你的活动“增长”。 - yital9

0
你需要: A. 使用Strings.xml文件 B. 将一个字符串更改为另一个字符串 - 例如:
<string name="example1">hi</string>
<string name="example2">hello</string>

在 strings.xml 文件中 然后在 Main 类中:

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

当字符串是example1时。 如果这不能帮助,我不知道还有什么能...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接