0

今天早上我大吃一惊,我没有找到一种方法来做我想做的事。我是 Android API 的新手。

我要做的是从由数据库触发的适配器更新 ListView。我创建了我的 Activity,在其中创建了我的列表视图并在其上设置了我的自定义适配器(BaseAdapter 的子级),该适配器适应了由海关对象(AP)构建的我的数组列表。我启动了一个异步任务,它将每 2 秒扫描一次我的数据库以从中取回数据,更新我的数组列表(如果它不存在则添加一个对象)。我调用 doInBackground() 方法 publisProgress() 来触发 google API 上指定的 onProgressUpdate 方法。当我调用 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;
}

 }

适配器AP.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'constructor 并制作一个

(BaseAdapter)((ListView)list.getAdapter()) 

但它没有任何改变,因为它总是引用 UI 元素(实际上相同)。我采用可能来自 publishProgress(void) 的 NullPointerExecption,但我不明白为什么。

日志猫:

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

请教我如何正确地做我的事情,我真的不知道我是否朝着好的方向发展。

非常感谢你。

4

1 回答 1

1

这样做:

从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() ;
                        }
                    }
                });
于 2013-08-26T12:38:42.417 回答