今天早上我心烦意乱,我找不到办法去做我想做的事。 我是Android API的新手。
我要做的是从数据库触发的适配器更新ListView。 我创建了我的Activity,在其中创建了我的listview并在其上设置了我的自定义适配器(BaseAdapter的子节点),它适应我的海关对象(AP)构建的arraylist。我想要一个AsynchTask,它将每2秒扫描一次我的数据库以从中获取数据,更新我的arraylist(添加一个对象,如果它不存在)。 我调用doInBackground()方法publisProgress()来触发google API上指定的onProgressUpdate方法。 当我调用publishProgress()时,我的问题就出现了。 我认为原因是我的asynchTask尝试访问UI对象,而在Android(adapter.notifyDatasetUpdate)上则不可能。 我不知道如何解决它。
我的代码:
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) ;
}
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;
}
}
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,但我不明白为什么。
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
请教我如何正确地做我的东西,我真的不知道我是否朝着好的方向发展。
非常感谢你。
答案 0 :(得分: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() ;
}
}
});