今天早上我疯了,我没有找到做我想做的事的方法。我是安卓API的新手。
我要做的是从数据库触发的适配器更新ListView。我创建了我的"活动",在其中我创建了列表视图,并在上面设置了我的自定义适配器(BaseAdapter的子级),以调整由自定义对象(AP)构建的数组列表。我启动了一个AsynchTask,它将每2秒扫描我的数据库以从中获取数据,并更新我的arraylist(如果上面不存在对象,则添加一个对象)。我调用doInBackground()方法publisProgress()来触发onProgressUpdate方法,如在google API上指定的。当我调用publishProgress()我的应用程序出错时,就会出现问题。我认为原因是我的asynchTask试图访问UI对象,而这在Android上是不可能的(adapter.notifyDatasetUpdate)。我不知道该怎么修。
我的代码:
活动.java
public class MainActivity extends Activity {
ListView list ;
AdapterAP adapter ;
ArrayList<AP> listAp ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listAp = new ArrayList<AP>() ;
list = (ListView) findViewById(R.id.list) ;
adapter = new AdapterAP(this, listAp) ;
Db_th db_th = new Db_th(listAp, this,adapter) ;
list.setAdapter(adapter) ;
db_th.execute(listAp) ;
}
}
Db_th.java
public class Db_th extends AsyncTask<ArrayList<AP>, Void, String>{
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Toast.makeText(context, result, Toast.LENGTH_LONG).show() ;
}
ArrayList<AP> listAp= new ArrayList<AP>();
Context context ;
Activity activity ;
AdapterAP adapter;
public Db_th (ArrayList<AP> listAp, Context context , AdapterAP adapter) {
super() ;
this.listAp = listAp ;
this.context = context ;
//this.adapter = adapter ;
this.adapter = adapter ;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(ArrayList<AP>... params) {
//String ret = new String() ;
SQLiteDatabase db = SQLiteDatabase.openDatabase("/data/local/tmp/sniffer.db", null, SQLiteDatabase.OPEN_READONLY) ;
String get_ap = new String("SELECT * from ssid") ;
String count_ap = new String("SELECT COUNT(id) FROM ssid WHERE name=") ;
Cursor cursor ;
while (true) {
cursor = db.rawQuery(get_ap, null) ;
cursor.moveToFirst() ;
while (!cursor.isAfterLast()) {
if (!search_id(cursor.getInt(0)))
listAp.add(new AP(cursor.getInt(0), cursor.getString(1), cursor.getString(2), cursor.getInt(3), cursor.getFloat(4), cursor.getInt(5), null, null)) ; // NO PROBLEM WITH PASSING NULL
cursor.moveToNext() ;
}
publishProgress(null) ;
try {
Thread.sleep(2) ;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
protected void onProgressUpdate(Void... values) {
//super.onProgressUpdate(values); COMMENT HERE BECAUSE I READ THAT COULD SCREW UP APK
adapter.notifyDataSetChanged() ;
}
protected boolean search_id(int id) {
for (AP ap : listAp) {
if (ap.getId() == id)
return true ;
}
return false;
}
}
AdapterAP.java
public class AdapterAP extends BaseAdapter{
static class ViewHolder {
// MY FIELDS
}
private Activity activity ;
private ArrayList<AP> listAp ;
private static LayoutInflater layoutInflat ;
public AdapterAP(Activity activity, ArrayList<AP> listAp) {
this.activity = activity ;
this.listAp = listAp ;
layoutInflat = (LayoutInflater) this.activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE) ;
}
@Override
public int getCount() {
return listAp.size() ;
}
@Override
public Object getItem(int arg0) {
return listAp.get(arg0);
}
@Override
public long getItemId(int arg0) {
return arg0 ;
}
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder ;
if (convertView == null) {
convertView = layoutInflat.inflate(R.layout.row_ap, null) ;
// holder.creatingmyview
convertView.getTag() ;
} else {
holder = (ViewHolder) convertView.getTag() ;
}
//holder.doingmystuff
return convertView;
}
}
当然,我甚至试图将视图传递给我的asynctask构造函数,并制作一个
(BaseAdapter)((ListView)list.getAdapter())
但它什么也不改变,因为它总是引用一个UI元素(事实上也是如此)。我接受了一个可以来自publishProgress(void)的NullPointerExection,但我不明白为什么。
LogCat:
08-26 07:58:10.614: E/AndroidRuntime(2149): FATAL EXCEPTION: main
08-26 07:58:10.614: E/AndroidRuntime(2149): java.lang.NullPointerException
08-26 07:58:10.614: E/AndroidRuntime(2149): at com.example.wisniffer.Db_th.onProgressUpdate(Db_th.java:80)
08-26 07:58:10.614: E/AndroidRuntime(2149): at com.example.wisniffer.Db_th.onProgressUpdate(Db_th.java:1)
08-26 07:58:10.614: E/AndroidRuntime(2149): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:647)
08-26 07:58:10.614: E/AndroidRuntime(2149): at android.os.Handler.dispatchMessage(Handler.java:99)
08-26 07:58:10.614: E/AndroidRuntime(2149): at android.os.Looper.loop(Looper.java:137)
08-26 07:58:10.614: E/AndroidRuntime(2149): at android.app.ActivityThread.main(ActivityThread.java:5103)
08-26 07:58:10.614: E/AndroidRuntime(2149): at java.lang.reflect.Method.invokeNative(Native Method)
08-26 07:58:10.614: E/AndroidRuntime(2149): at java.lang.reflect.Method.invoke(Method.java:525)
08-26 07:58:10.614: E/AndroidRuntime(2149): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
08-26 07:58:10.614: E/AndroidRuntime(2149): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
08-26 07:58:10.614: E/AndroidRuntime(2149): at dalvik.system.NativeStart.main(Native Method)
08-26 07:58:12.924: I/Process(2149): Sending signal. PID: 2149 SIG: 9
请教我如何正确地做我的事情,我真的不知道我是否朝着好的方向前进。
非常感谢。
这样做:
从onProgressUpdate()方法中删除此行
adapter.notifyDataSetChanged() ;
并覆盖onPostExecute()方法,并将此行放入其中,如下所示:
@Override
protected void onPostExecute(ArrayList<HashMap<String, String>> result) {
super.onPostExecute(result);
adapter.notifyDataSetChanged() ;
}
更新
runOnUiThread(new Runnable() {
@Override
public void run() {
if(adapter!=null){
adapter.notifyDataSetChanged() ;
}
}
});