Asynctask AdapterBase PublishProgress не работает (приложение не работает)

Я взорвал себе мозг сегодня утром, я не нашел способ делать то, что хочу. Я новичок в Android API.

Что я делаю, так это обновляю ListView из адаптера, запускаемого базой данных. Я создаю свою активность, внутри которой я создаю свой список и устанавливаю на нем свой собственный адаптер (дочерний элемент BaseAdapter), который адаптирует мой список массивов, созданный таможенными объектами (AP). Я запускаю AsynchTask, который будет сканировать каждые 2 секунды мою базу данных, чтобы получить из нее данные, обновить мой список массивов (добавить объект, если он не существует в нем). Я вызываю doInBackground() метод publisProgress() для запуска метода onProgressUpdate, как указано в API Google. Мои проблемы возникают, когда я вызываю publishProgress(), и мое приложение облажается. Я думаю, причина в том, что мой asynchTask пытается получить доступ к объектам пользовательского интерфейса, а это невозможно на Android (adapter.notifyDatasetUpdate). У меня нет идей, как это исправить.

Мой код:

Activity.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 вид и сделать

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

но это ничего не меняет, потому что всегда ссылается на элемент пользовательского интерфейса (фактически то же самое). Я беру NullPointerExecption, который может исходить от publishProgress(void), но не понимаю, почему.

Логкат:

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

Пожалуйста, научите меня, как правильно делать свои вещи, я действительно не знаю, в правильном ли я направлении.

Большое спасибо.


person deadeert    schedule 26.08.2013    source источник
comment
А если раскомментировать строку? Можете ли вы показать нам трассировку стека?   -  person Skaard-Solo    schedule 26.08.2013
comment
Привет, я не знаю, как получить трассировку стека в ADT IDE, где ее можно получить? Что вы подразумеваете под раскомментированной строкой?   -  person deadeert    schedule 26.08.2013


Ответы (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() ;
                        }
                    }
                });
person Biraj Zalavadia    schedule 26.08.2013
comment
Привет, спасибо за ваш ответ, я не думаю, что это сработает, потому что я никогда не заканчиваю свой цикл в doInBackground. Эта асинхронная задача никогда не заканчивается, поэтому мне действительно нужно использовать метод прогресса. Я прав ? - person deadeert; 26.08.2013