【问题标题】:Listview not updated on notifyDataSetChanged列表视图未在 notifyDataSetChanged 上更新
【发布时间】:2017-01-12 17:20:14
【问题描述】:

在我的程序中,我有一个显示 SQL 数据库中各种客户信息的列表视图和一个用于清除数据库中所有客户条目的按钮。我的问题是:

  1. 当数据库为空时,应用会崩溃。
  2. 当有新的客户条目时,列表视图不会更新。一世 试过 notifyDataSetChanged() 和 notifyDataSetInvalidated(), 但列表视图仍未更新。

我的主程序:

package attendance.emily.example.com.attendance;


import android.os.AsyncTask;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;

import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import org.json.JSONArray;

import org.json.JSONObject;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;



public class MainActivity extends AppCompatActivity {

    Button cleardata;
    TextView textview3, displayUser, displayTimeout, displayTimein, textview7;
    ListView lv;
    ArrayAdapter<String> adapter;

    String address = "http://192.168.0.100:80/gps/get_logout.php";


    InputStream is = null;

    String line = null;

    String result = null;

    String data[];






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


        lv = (ListView) findViewById(R.id.listView1);


        cleardata = (Button) findViewById(R.id.button);
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();

        StrictMode.setThreadPolicy(policy);

        StrictMode.setThreadPolicy((new StrictMode.ThreadPolicy.Builder().permitNetwork().build()));
        getdata3();


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





        cleardata.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                String link = "http://192.168.0.100:80/gps/delete.php"; //using this IP for Genymotion emulator
                new updateData().execute(link);
                Toast.makeText(MainActivity.this, "Executed", Toast.LENGTH_LONG).show();
            }
        });




    }

    public class updateData extends AsyncTask<String, String, String> {

        @Override
        protected String doInBackground(String... params) {
            HttpURLConnection conn = null;

            try {
                URL url;
                url = new URL(params[0]);
                conn = (HttpURLConnection) url.openConnection();
                if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    InputStream is = conn.getInputStream();
                } else {
                    InputStream err = conn.getErrorStream();
                }
                return "Done";
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (conn != null) {
                    conn.disconnect();
                }
            }
            return null;
        }

    }



private void getdata3()
{
    try{
        URL url = new URL(address);
        HttpURLConnection con = (HttpURLConnection)url.openConnection();
        con.setRequestMethod("GET");
        is = new BufferedInputStream(con.getInputStream());



    } catch(Exception e){
        e.printStackTrace();
    }

    try{
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        while ((line=br.readLine()) != null){
            sb.append(line+"\n");

        }

        is.close();
        result = sb.toString();





    } catch(Exception e){
        e.printStackTrace();
    }

    try {
        String a="";
        String p="";
        String z="";
        JSONArray ja = new JSONArray(result);
        JSONObject jo = null;




        data=new String[ja.length()];


        for (int i=0; i<ja.length(); i++ ){
            jo = ja.getJSONObject(i);
           a =jo.getString("user");
            p = jo.getString("MIN(timein)");
            z = jo.getString("MAX(timeout)");


            data[i] = "User: "+ a + "\n" +"Time In: " + p + "\n" + "Time Out: " + z+"\n"   ;



        }

    }
    catch(Exception e){
        e.printStackTrace();
    }

}










}

错误:

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: attendance.emily.example.com.attendance, PID: 11833
                  java.lang.RuntimeException: Unable to start activity ComponentInfo{attendance.emily.example.com.attendance/attendance.emily.example.com.attendance.MainActivity}: java.lang.NullPointerException: storage == null
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2596)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2653)
                      at android.app.ActivityThread.access$800(ActivityThread.java:156)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1355)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:157)
                      at android.app.ActivityThread.main(ActivityThread.java:5872)
                      at java.lang.reflect.Method.invokeNative(Native Method)
                      at java.lang.reflect.Method.invoke(Method.java:515)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:674)
                      at dalvik.system.NativeStart.main(Native Method)
                   Caused by: java.lang.NullPointerException: storage == null
                      at java.util.Arrays$ArrayList.<init>(Arrays.java:38)
                      at java.util.Arrays.asList(Arrays.java:155)
                      at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:128)
                      at attendance.emily.example.com.attendance.MainActivity.onCreate(MainActivity.java:73)
                      at android.app.Activity.performCreate(Activity.java:5312)
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1111)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2552)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2653) 
                      at android.app.ActivityThread.access$800(ActivityThread.java:156) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1355) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:157) 
                      at android.app.ActivityThread.main(ActivityThread.java:5872) 
                      at java.lang.reflect.Method.invokeNative(Native Method) 
                      at java.lang.reflect.Method.invoke(Method.java:515) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:674) 
                      at dalvik.system.NativeStart.main(Native Method) 

关于如何解决我的问题的任何建议?

【问题讨论】:

  • LogCat 将有助于解决该崩溃问题。另外,我在您的AsyncTask 中没有看到onPostExecute()?这是我期望填充列表的位置。
  • @KickingLettuce 嗨,我是 android 新手,我正在关注 youtube 上有关如何创建列表视图以显示数据库信息的教程,youtuber 根本不会创建 onPostExecute()。抱歉,我必须在 onPostExecute() 中写什么?我已经更新了我的 logcat。
  • 基本上doInBackground()的结果作为参数传递给onPostExecute()。虽然我经常return null (indoInBackground()) 所以我有那个 (onPostExecute()) 作为void 函数。关键是,它在后台“获取数据”线程完成后运行 (onPostExecute())。因此,如果您在后台填充ArrayArrayList&lt;&gt;,您可以将其设为类参数(或只是传递它)并在onPostExecute() 中使用它并用它填充您的adapter。链接:developer.android.com/reference/android/os/AsyncTask.html
  • @KickingLettuce 我已添加,protected void onPostExecute(String s) { adapter.notifyDataSetChanged(); super.onPostExecute(s); }
  • 没关系,只要在您更新适配器并添加新信息之后完成。我建议也使用 ArrayList 而不是 Array。当您想添加新数据时会更容易。

标签: android sql listview


【解决方案1】:

在调用adapter.notifyDataSetChanged(); 之前,您必须更新adapter(或它保存的数据),如下所示:

String s = "new item";
adapter.add(s);

然后

adapter.notifyDataSetChanged(); 

但是,更好的方法:

由于您使用的是String[],因此您无法向其中添加项目。我建议使用ArrayList&lt;String&gt; list = new ArrayList&lt;String&gt;();,然后像现在一样使用它填充您的适配器。

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

然后,当您想添加新项目时,请执行以下操作:

list.add(s);
adapter.notifyDataSetChanged(); 

所以如果你想显示一个新的列表项,首先更新列表,然后调用notifyDataSetChanged()。旁注:您也可以以相同的方式更新现有行,但您必须获取位置,通常从 onClick 方法传入。

Here is another great questions on this with good answers

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-16
    • 2013-12-27
    相关资源
    最近更新 更多