【发布时间】:2017-01-12 17:20:14
【问题描述】:
在我的程序中,我有一个显示 SQL 数据库中各种客户信息的列表视图和一个用于清除数据库中所有客户条目的按钮。我的问题是:
- 当数据库为空时,应用会崩溃。
- 当有新的客户条目时,列表视图不会更新。一世 试过 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())。因此,如果您在后台填充Array或ArrayList<>,您可以将其设为类参数(或只是传递它)并在onPostExecute()中使用它并用它填充您的adapter。链接:developer.android.com/reference/android/os/AsyncTask.html -
@KickingLettuce 我已添加,protected void onPostExecute(String s) { adapter.notifyDataSetChanged(); super.onPostExecute(s); }
-
没关系,只要在您更新适配器并添加新信息之后完成。我建议也使用 ArrayList
而不是 Array。当您想添加新数据时会更容易。