-1

У меня есть следующие одноточечно работает для моего Android приложенияStop Андроида adapter.notifyDataSetChanged() от работы параллельно с функцией, которая содержит код notifyDataSetChanged()

public class ListsApplication extends Application { 
public DbxDatastoreManager datastoreManager; 
public HashMap<String, ViewItemContainer> itemsSync; 
public Typeface Font; 
public boolean Fetch; 

private static ListsApplication singleton; 
public static ListsApplication getInstance() { 
    return singleton; 
} 

@Override 
public void onCreate() { 
    super.onCreate(); 
    singleton = this; 
    itemsSync = new HashMap<>(); 
    Font = Typeface.createFromAsset(getAssets(), "fonts/GoodDog.otf"); 
    Fetch = true; 
}} 

затем из дома активности я сохраняю одиночки экземпляр через

ListsApplication app = app.getInstance 

в настройках Главная деятельность I слушатель, который запускается из хранилища данных онлайн сервера всякий раз, когда есть изменение в онлайн датасторов через

private void setUpListeners() { 
    app.datastoreManager.addListListener(new DbxDatastoreManager.ListListener() { 
     @Override 
     public void onDatastoreListChange(DbxDatastoreManager dbxDatastoreManager) { 
      // Update the UI when the list of datastores changes. 
      new Handler().postDelayed(new Runnable() { 
       @Override 
       public void run() { 
        app.Fetch = true; 
        Home.this.updateList(); 
        app.Fetch = false; 

       } 
      }, 7000/* 3sec delay */); 

      Toast toast = Toast.makeText(getApplicationContext(), "RECEIVED", Toast.LENGTH_SHORT); 
      toast.show(); 
     } 
    }); 

    updateList(); 
    app.Fetch = false; 
} 

Я разрешаю некоторое время до запуска updateList(), поскольку обновление хранилища данных не является атомарным, поэтому требуется, чтобы все строки в онлайновом хранилище данных занимали 2 секунды, игнорируйте приложение. позже объясним.

updateList() очищает ArrayList элементов, которые должны заполнить listAdapter и работает adapter.notifyDataSetChanged()

В моей пользовательской listAdapter, я задал GetView следующим образом:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    final ViewHolder mHolder; 
    if (convertView == null) { 
     /*Toast toast = Toast.makeText(context, "nullConvertView", Toast.LENGTH_SHORT); 
     toast.show();*/ 
     mHolder = new ViewHolder(); 
     LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     convertView = inflater.inflate(R.layout.listitem, parent, false); 


     mHolder.PetName = (TextView) convertView.findViewById(R.id.PetName); 
     mHolder.BuyFood = (ImageView) convertView.findViewById(R.id.PetBuyFood); 
     mHolder.PetImage = (RoundedImageView) convertView.findViewById(R.id.PetImage); 





     convertView.setTag(mHolder); 
    } else { 
     mHolder = (ViewHolder) convertView.getTag(); 
    } 
    updateItem(mHolder, this.getItem(position));return convertView;} 

и updateItem (mHolder, this.getItem (позиция))

public void updateItem(final ViewHolder currentViewFromList, final DbxDatastoreInfo info){ 
    app = ListsApplication.getInstance(); 
    if (app.itemsSync.containsKey(info.id) && !app.Fetch){ 
     /*Toast toast = Toast.makeText(context, "not fetching "+info.title, Toast.LENGTH_SHORT); 
     toast.show();*/ 
     ViewItemContainer cont = app.itemsSync.get(info.id); 
     currentViewFromList.PetName.setTypeface(app.Font); 
     currentViewFromList.PetName.setText(cont.PetName); 
     currentViewFromList.PetImage.setImageBitmap(cont.PetImage); 
     if (cont.BuyFood) currentViewFromList.BuyFood.setVisibility(View.VISIBLE); 
     else currentViewFromList.BuyFood.setVisibility(View.INVISIBLE); 
    } 
    else{ 
     ViewItemContainer cont = new ViewItemContainer(); 
     try { 
     Toast toast = Toast.makeText(context, "entrato"+info.title, Toast.LENGTH_SHORT); 
     toast.show(); 

     DbxDatastore datastore = app.datastoreManager.openDatastore(info.id); 
     datastore.sync(); 

     if (info.title!=null){ 
      currentViewFromList.PetName.setTypeface(app.Font); 
      cont.PetName = info.title; 
      currentViewFromList.PetName.setText(cont.PetName); 
     } 

     DbxTable table = datastore.getTable("ITEMS"); 
     DbxRecord record = table.get("INFO"); 

     if (record!=null && record.hasField("PETPICTURE")){ 
      byte[] b = record.getBytes("PETPICTURE"); 
      //Bitmap picture = Misc.ByteArrayToImg(b); 
      cont.PetImage = Misc.ByteArrayToImg(b); 
      if (cont.PetImage!=null) currentViewFromList.PetImage.setImageBitmap(cont.PetImage); 
     } else currentViewFromList.PetImage.setImageResource(R.drawable.ic_launcher); 


     if (record!=null){ 
      cont.BuyFood = record.getBoolean("BUYFOOD"); 
      if (cont.BuyFood) currentViewFromList.BuyFood.setVisibility(View.VISIBLE); 
      else currentViewFromList.BuyFood.setVisibility(View.INVISIBLE); 
     } 


     datastore.close(); 
    } catch (DbxException e) { 
     e.printStackTrace(); 
    } 

     app.itemsSync.put(info.id,cont); 
    } 

} 

в основном при запуске приложения, app.Fetch устанавливается истина, updateList() из дома создает тыс e адаптер и вызовы adapter.notifyDataSetChanged().

На данный момент listAdapter GetView вызывается для каждого элемента в списке, проверяет идентификатор в качестве ключа в HashMap и не находит поэтому она извлекает данные из хранилища данных, и вставляет данные в hashmap и на представлении.

До этого момента все хорошо. Список просматривается правильно, и когда прокручиваются представления, данные извлекаются правильно из хэш-карты, а не извлекаются из хранилища данных снова и снова.

Затем с другого телефона я добавляю новое хранилище данных, которое запускает слушателя, и на моем телефоне отображается «ПОЛУЧЕННЫЙ» тост, что означает, что слушатель был запущен. app.Fetch возвращает true, а затем вызывается updateList().

Если я проверяю значение app.Fetch в любом месте updateList(), оно по-прежнему установлено в true, тогда как если я проверю его при запуске кода getView, оно будет установлено в false, чтобы оно снова извлекало данные из хэш-карты, а не получение обновленных онлайновых хранилищ данных.

Я думаю, что код GetView начинает работать параллельно с функцией updateList поэтому она показывает следующее поведение:

булевой правда updateList() начать adapter.notifyDataSetChanged() работает ListAdapter GetView начать updateList () заканчивается boolean false getView проверяет логическое значение, и поскольку в данный момент он является ложным, он извлекает данные из хэш-карты.

Есть ли способ получить updateList, чтобы ждать, пока все элементы в представлении списка будут проходить через getView?

+0

Существует ли имя этого метода адаптера 'getView' или' fetchTheData'? – Selvin

+0

Это getView (int position, View convertView, родительская группа ViewGroup) – Venzo92

ответ

0

Да, вы убедитесь, что вы вызываете notifyDataSetChanged в потоке пользовательского интерфейса. Таким образом вы никогда не будете называть его во время загрузки списка. Если вы хотите вызвать его в асинхронном потоке, используйте блок runOnUiThread, чтобы переместить этот вызов в поток пользовательского интерфейса. Это гарантирует, что вы никогда не будете пытаться обновлять список во время его рисования и избегать всей проблемы.