2015-12-03 2 views
0

У меня есть ListView, который я заполняю данными из DataStore или из моей локальной базы данных.Listview не обновляется автоматически после получения данных списка из DataStore

Я проверяю некоторые условия, которые будут определять, будет ли я получать данные из DataStore или базы данных. Когда я извлекаю из базы данных, ListView автоматически обновляется, но когда я извлекаю из DataStore, это не так. Затем мне нужно щелкнуть мой TextView, который ниже ListView, и когда я нажимаю на него, появляется мягкая клавиатура, а затем мой ListView заполняется данными из DataStore.

Моя деятельность, которая имеет ListView:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_xyz); 

    list_View = (ListView) findViewById(R.id.data_listView); 
    list_View.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); 
    list_View.setMultiChoiceModeListener(new Selector()); 

    adapter = new MyAdapter(context,Long.valueOf(id),isOnline()); 
    list_View.setAdapter(adapter); 
    list_View.setSelection(adapter.getCount() - 1); 
    adapter.registerDataSetObserver(new DataSetObserver() { 
     @Override 
     public void onChanged() { 
      super.onChanged(); 
      list_View.setSelection(adapter.getCount() - 1); 
     } 

    LoadDataTask ldt = new LoadDataTask(); 
    ldt.execute("123456789"); 
} 

private void loadDataFromDataStore(final Long contactId){ 
    final ArrayList<Data> data = new ArrayList<>();; 
    d("loadingdataFromDatasore"); 

    GetDataTask task = new GetDataTask(new ApiTask.ResultListener() { 
     @Override 
     public void successHook(Object o) { 
      if (o instanceof GetDataResponse) { 
       GetDataResponse res = (GetDataResponse) o; 
       if (res.getData() != null && res.getData().getItems() != null) { 
        for (ListDataItem i : res.getData().getItems()) { 
         Data dp = new Data(i.getPosition(), i.getMessage(), i.getDateCreated(),i.getMessageId(),1); 
         adapter.addFromOtherThread(dp); 
        } 

       } 

       d("Messages loaded from server: " + adapter.getCount()); 
      } 

     } 
} 

public class LoadDataTask extends AsyncTask<String,String,Void> { 
     @Override 
    protected Void doInBackground(String... params){ 

     if(isOnline && isFirstTime){ 
     loadDataFromDataStore(Long.valueOf(params[0])); 
     }else{ 
      //load from database 
     } 

     return null; 
    } 

@Override 
    protected void onPostExecute(Void v){ 
     adapter.notifyDataSetChanged(); 

    } 
} 

Мой адаптер класс, который расширяет BaseAdapter (я удалил ненужный код для этого вопроса):

public class DataAdapter extends BaseAdapter { 

private ArrayList<Data>data_list; 

public DataAdapter(){ 
    data_list = new ArrayList<>(); 
} 

public void addFromOtherThread(Data object) { 
    data_list.add(object); 
} 

Что я упускаю что делает ListView не автоматически обновлять себя даже после звонка notifyDatasetChanged()?

+0

Да, вы должны использовать notifyDatasetChanged() после добавления данных в свой список. – Avi

+0

@Avi i dint понять ваш комментарий –

+0

Вы используете 'notifyDataSetChanged' - ваш метод doInBackground, который вызывает проблему, я думаю. Для этого вы можете вернуть данные, полученные из метода successHook, а затем использовать метод 'addFromOtherThread' в вашем' onPostExecution' с 'notifyDataSetChanged', который будет показывать новые данные в listview. – Pankaj

ответ

1
@Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_xyz); 

     list_View = (ListView) findViewById(R.id.data_listView); 
     list_View.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); 
     list_View.setMultiChoiceModeListener(new Selector()); 

     adapter = new MyAdapter(context,Long.valueOf(id),isOnline()); 
     list_View.setAdapter(adapter); 
     list_View.setSelection(adapter.getCount() - 1); 
     adapter.registerDataSetObserver(new DataSetObserver() { 
      @Override 
      public void onChanged() { 
       super.onChanged(); 
       list_View.setSelection(adapter.getCount() - 1); 
      } 
    loadDataFromDataStore("123456789") 

    } 

    private void loadDataFromDataStore(final Long contactId){ 
     final ArrayList<Data> data = new ArrayList<>();; 
     d("loadingdataFromDatasore"); 

     new GetDataTask(new ApiTask.ResultListener() { 
      @Override 
      public void successHook(Object o) { 
       if (o instanceof GetDataResponse) { 
        GetDataResponse res = (GetDataResponse) o; 
        if (res.getData() != null && res.getData().getItems() != null) { 
         for (ListDataItem i : res.getData().getItems()) { 
          Data dp = new Data(i.getPosition(), i.getMessage(), i.getDateCreated(),i.getMessageId(),1); 
          adapter.addFromOtherThread(dp); 
         } 

        }  
        d("Messages loaded from server: " +  adapter.getCount()); 
adapter.notifyDatasetChanges(); 
       } 

      } 
    }.execute(); 
} 

GetDataTask должен работать на фоне внутри, вам не нужно начинать с AsyncTask.

Если вы хотите использовать AsyncTask, то ваша AsyncTask должна ждать результата GetDataTask, который он не выполняет в реализации вашего кода. Я не знаю, какие рамки вы используете для создания вызова api, но ваша реализация кажется неправильной.

Я написал код на основе предположений, если ваш GetDataTask является AsyncTask или некоторым фоновым процессором, он будет работать отлично.

+0

Но я думаю, что это не сработало, потому что его все еще в методе doInBackground – Pankaj

+0

@Avi Я не знаю, что сказать, но человек, ** ты спас мой день **. это правильное решение. i nevwr подумал, что вызов asyn-задачи внутри другой задачи asyn может привести к неисправности. 'GetDataTask' - это asyn-задача **, которая расширяет другую задачу asyn **. 'GetDataTask' вызывает базовый класс, который загружает объекты из хранилища данных и передает результаты в' новый ApiTask.ResultListener() '. Благодаря Avi –

2

изменение:

@Override 
    protected void onPostExecute(Void v){ 
     adapter.notifyDataSetChanged(); 

    } 
} 

к:

@Override 
    protected void onPostExecute(Void v){ 
     adapter.notifyDataSetChanged(); 
     list_View.setAdapter(adapter); 

    } 
} 

Позвольте мне знать, если дополнительные разъяснения требует комментариев ниже.

+0

Вам не нужно 'setAdapter', если вы делаете' notifyDataSetChanged' – Pankaj

+0

@Sangeeta все еще не меняет –

+0

@Clairvoyant, что мне делать, потому что Sangeeta отвечает din't? –

Смежные вопросы