简体   繁体   English

无法在onPostExecute中更新android listview

[英]Can't update android listview in onPostExecute

I have this in my onCreate method: 我在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();
        }
    });

}

The above code populates a listView with the content of myStringArray , for now everything is ok. 上面的代码使用myStringArray的内容填充listView,现在一切正常。 The problem comes when I call new loadJson().execute(); 当我调用new loadJson().execute(); it executes fine and here is the method's code: 它执行正常,这是方法的代码:

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

}

As you can see I'm updating the hardcoded content of myStringArray with the new values fetched into newArray . 正如您所看到的,我正在使用提取到newArray的新值更新myStringArray的硬编码内容。 Now I'm unable to see the new content. 现在我无法看到新内容。 I know it's there, but how can I tell to the current activity: "Hey, I updated your array, please show it!" 我知道它在那里,但我怎么能告诉当前的活动:“嘿,我更新你的阵列,请显示它!” ?

I know that I'm missing something really small, but as a beginner, I'm not able to spot it. 我知道我错过了一些非常小的东西,但作为初学者,我无法发现它。

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

inside your onPostExecute you can try following : 在您的onPostExecute中,您可以尝试以下操作:

ListView listView = (ListView) findViewById(R.id.topJokesList);
listView.getAdapter().notifyDataSetChanged();
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;

} }

In your above code you are using some peace of code which is actually reside in worker thread(doInBackgroud()) method so cut this code and paste into doInBackgound method. 在上面的代码中,您正在使用一些实际驻留在工作线程(doInBackgroud())方法中的代码,因此请将此代码剪切并粘贴到doInBackgound方法中。 then keep this code in onPostExecute method and declare listview and arrayadapter before oncreate method ie, Global 然后将此代码保存在onPostExecute方法中,并在oncreate方法之前声明listview和arrayadapter,即Global

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

I hope this will help you... 我希望这能帮到您...

I found the answer to this question because I was searching for the answer myself. 我找到了这个问题的答案,因为我自己正在寻找答案。 There are a few close answers here, but they leave out pieces which will never get you to the answer. 这里有一些接近的答案,但是他们遗漏了一些永远不会让你得到答案的作品。

First of all add two member variables to your AsyncTask class: 首先在AsyncTask类中添加两个成员变量:

private ListView listView;
private Activity activity;

Next, add a constructor to you AsyncTask class which takes an Activity: 接下来,向您的AsyncTask类添加一个构造函数,该类接受一个Activity:

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

Now, when you new up your AsyncTask class and call execute() you will add the reference to the Activity which called it (the this value passed in when you construct your AsyncTask class). 现在,当您新建AsyncTask类并调用execute()时,您将添加对调用它的Activity的引用(在构造AsyncTask类时传入值)。

new loadJson(this).execute(param);

Finally, back in your AsyncTask you will write the code for your postExecute() which looks like the following: 最后,在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();
    }

You have to have a reference to your Activity so you can call the findViewById. 您必须引用您的Activity,以便可以调用findViewById。 Note that the targetListView is the id of your ListView which is on your original Activity. 请注意,targetListView是ListView的id,它位于原始Activity上。

We've sent that Activity into the AsyncTask's constructor so it is available. 我们已将该Activity发送到AsyncTask的构造函数中,因此它可用。 Now you can get the Adapter and add your value to you and call notifyDataSetChanged() so it will update on your UI. 现在您可以获取适配器并将值添加到您并调用notifyDataSetChanged(),以便它在您的UI上更新。

I'm using this code in my solution and it works great. 我在我的解决方案中使用此代码,效果很好。

You can switch from array to ArrayList and call adapter.notifyDataSetChanged, after updating array list content (but dont create new ArrayList instance, update must be on the same reference as was provided to ArrayAdapter). 在更新数组列表内容之后,您可以从数组切换到ArrayList并调用adapter.notifyDataSetChanged(但是不要创建新的ArrayList实例,update必须与提供给ArrayAdapter的引用相同)。

Or repeat following code (from onCreate) in your AsyncTask.onPostExecute: 或者在AsyncTask.onPostExecute中重复以下代码(来自onCreate):

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

You need to: A. Use the Strings.xml file B. Change the string from one to another - eg 您需要:A。使用Strings.xml文件B.将字符串从一个更改为另一个 - 例如

<string name="example1">hi</string>
<string name="example2">hello</string>

in the strings.xml file and then in the Main class: 在strings.xml文件中,然后在Main类中:

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

when the string is example1. 当字符串是example1时。 If this didn't help, I don't know what will... 如果这没有帮助,我不知道会是什么......

you can add your adapter in the asynctask constructor : 您可以在asynctask构造函数中添加适配器:

In your activity : 在您的活动中:

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

You can declare in LoadJson: 你可以在LoadJson中声明:

private  ArrayAdapter<String> mAdapter;

In the constructor, you get the adapter from activity : 在构造函数中,您从活动中获取适配器:

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

So In your postExecute, you can update the adapter. 所以在你的postExecute中,你可以更新适配器。 Hope it helps! 希望能帮助到你!

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

Just add a reference of Adapter into your AsyncTask: 只需将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
        }
    }

}

Then 然后

new loadJson(adapter).execute();  

And now your can update your Adapter in onPostExecute 现在您可以在onPostExecute更新您的Adapter

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM