2013-04-23 3 views
12

У меня есть база данных на сервере и из планшета. Я беру некоторые значения из одной таблицы в базе данных. Я правильно загружаю эту информацию в список, но я хотел бы знать, почему, когда происходит изменение, ничего не происходит, даже если я использую notifyDataSetChanged();. Я должен сказать, что для загрузки данных загрузки y использует AsyncTaskClass Итак, моя проблема заключается в том, что я не знаю, пользуетесь ли функцией notifyDataSetChanged(); метод правильно, потому что если есть изменение, я хотел бы обновить изображение. Вот некоторая часть кода этого класса:Android: notifyDataSetChanged(); не работает

@Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.all_candidatos); 


     candidatosList = new ArrayList<HashMap<String, String>>(); 

     new CargarCandidatos().execute(); 
    } 


// public void timer(){ 
//  new CountDownTimer(tiempo, 100) { 
// 
//    public void onTick(long millisUntilFinished) { 
//     
//    } 
// 
//    public void onFinish() { 
//    // new CargarCandidatos().execute(); 
// 
//    } 
//   }.start();} 



    /** 
    * Background Async Task to Load all product by making HTTP Request 
    * */ 
    class CargarCandidatos extends AsyncTask<String, String, String> { 

     /** 
     * Before starting background thread Show Progress Dialog 
     * */ 
     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 
      pDialog = new ProgressDialog(Monitorizacion.this); 
      pDialog.setMessage("Loading ..."); 
      pDialog.setIndeterminate(false); 
      pDialog.setCancelable(false); 
      pDialog.show(); 
     } 

     /** 
     * getting All products from url 
     * */ 
     protected String doInBackground(String... args) { 
      List<NameValuePair> params = new ArrayList<NameValuePair>(); 
      JSONObject json = jParser.makeHttpRequest(url_candidatos, "GET", params); 

      Log.d("Candidatos: ", json.toString()); 

      try { 
       int success = json.getInt(TAG_SUCCESS); 

       if (success == 1) { 

        candidatos = json.getJSONArray(TAG_CANDIDATOS); 

        for (int i = 0; i < candidatos.length(); i++) { 
         JSONObject c = candidatos.getJSONObject(i); 

         // Storing each json item in variable 
         String nserie = c.getString(TAG_NSERIE); 
         String dni = c.getString(TAG_DNI); 
         String nombre = c.getString(TAG_NOMBRE); 
         String test = c.getString(TAG_TEST); 
         String pregunta = c.getString(TAG_PREGUNTA); 
         String bateria = c.getString(TAG_BATERIA); 

         // creating new HashMap 
         HashMap<String, String> map = new HashMap<String, String>(); 

         // adding each child node to HashMap key => value 
         map.put(TAG_NSERIE, nserie); 
         map.put(TAG_DNI, dni); 
         map.put(TAG_NOMBRE, nombre); 
         map.put(TAG_TEST, test); 
         map.put(TAG_PREGUNTA, pregunta); 
         map.put(TAG_BATERIA, bateria); 

         // adding HashList to ArrayList 
         candidatosList.add(map); 
        } 
       } 
      } catch (JSONException e) { 
       e.printStackTrace(); 
      } 

      return null; 
     } 

     /** 
     * After completing background task Dismiss the progress dialog 
     * **/ 
     protected void onPostExecute(String file_url) { 
      pDialog.dismiss(); 
      runOnUiThread(new Runnable() { 
       public void run() { 
        /** 
        * Updating parsed JSON data into ListView 
        * */ 
        adapter = new SimpleAdapter(
          Monitorizacion.this, candidatosList, 
          R.layout.list_item, new String[] { TAG_NSERIE, 
            TAG_DNI, TAG_NOMBRE, TAG_TEST, TAG_PREGUNTA, TAG_BATERIA}, 
          new int[] { R.id.id, R.id.dni, R.id.nombre, R.id.test, R.id.pregunta, R.id.bateria}); 
        setListAdapter(adapter); 
        adapter.notifyDataSetChanged(); 
       // timer(); 
       } 
      }); 

     } 

    } 
} 
+0

никаких сбоев? вы не хотите, чтобы runOnUIThread просто установил адаптер. Убедитесь, что candidatosList имеет некоторые значения. – Triode

+0

Привет Triode, я загружаю все значения базы данных на экран, и активность не сбой. проблема в том, что даже база данных обновляется, пользовательский интерфейс не обновляется новыми значениями. – Katherine99

+0

@ Katherine99, если мой ответ решает проблему ур, вы можете отметить ответ как выбранный. :) –

ответ

68

Одна из главных причин notifyDataSetChanged() не будет работать для вас - это,

Ваш адаптер теряет ссылку на свой список.

Когда вы сначала инициализируете Adapter, он берет ссылку на ваш arrayList и передает его своему суперклассу. Но если вы повторно инициализируете существующий arrayList, он потеряет ссылку и, следовательно, канал связи с Adapter.

При создании и добавлении нового списка в Adapter. Всегда следуйте этим рекомендациям:

  1. Инициализировать arrayList, объявив его глобально.
  2. Добавить список в адаптер напрямую с проверкой нулевого и пустого значений . Установите адаптер в список напрямую (не проверяйте состояние ). Адаптер гарантирует, что везде, где вы делаете , изменение данных arrayList позаботится об этом, но никогда не потеряйте ссылку .
  3. Всегда изменять данные в самом ArrayList (если ваши данные полностью новый , чем вы можете позвонить adapter.clear() и arrayList.clear() перед тем фактически добавления данных в список), но не установлен адаптер т.е. если новые данные заселена в arrayList, чем просто adapter.notifyDataSetChanged()

Оставайтесь верны документации.

+2

Большое вам спасибо, моя проблема не была в доверии к власти адаптера. –

+1

Большое спасибо, с вашим объяснением. Я понял много вещей об адаптере и просмотре списка, также нашел решения для многих из моих сомнений. –

+1

Спасибо за это ясное объяснение. – huseyin

3

Адаптер определяет компоновку макета! -> setListAdapter(): Определите адаптер для ListView/GridView/Gallery ... , но вам нужно указать данные!

Я рекомендую вам инициализировать 'setListAdapter' в 'onCreate' или в конструкторе. После того, как вы установили данные в адаптер (например: adapter.setItem (yourData))

И ТЕПЕРЬ! Вы должны позвонить notifyDataSetChanged! Поскольку вы изменили данные, но вид не освежают и notifydatasetchanged() перезагрузить содержимое представления (ListView/GridView/Галерея ...)

Для хорошей практики и понять правильно, я рекомендую вы использовать «пользовательский адаптер» с помощью «baseAdapter»

Чтение и сделать этот учебник (я бессмыслица научиться с этим): http://www.androidhive.info/2012/02/android-custom-listview-with-image-and-text/

Читайте документацию: http://developer.android.com/reference/android/widget/BaseAdapter.html

+0

Спасибо anthony, я прочитаю эти веб-страницы, и я дам вам знать результаты – Katherine99

4

Что вам нужно изменить это положить ваши

runOnUiThread(new Runnable() { 
       public void run() { 
        /** 
        * Updating parsed JSON data into ListView 
        * */ 
        adapter = new SimpleAdapter(
          Monitorizacion.this, candidatosList, 
          R.layout.list_item, new String[] { TAG_NSERIE, 
            TAG_DNI, TAG_NOMBRE, TAG_TEST, TAG_PREGUNTA, TAG_BATERIA}, 
          new int[] { R.id.id, R.id.dni, R.id.nombre, R.id.test, R.id.pregunta, R.id.bateria}); 
        setListAdapter(adapter); 
        adapter.notifyDataSetChanged(); 
       // timer(); 
       } 
      }); 

в OnCreate(). и верните список candidatosList из Asynctask. чем установить таймер для обновления списка candidatosList.

+0

Простите, он продолжается без обновления – Katherine99

+0

Пожалуйста, проверьте Редактированный. – user1621629

+0

Привет, если я использую candidatosList.clear(); представление списка не кодирует какие-либо данные, когда я запускаю действие – Katherine99

1

Как Hissain describes above,

вам нужно сохранить ссылку на список

Вот как я получил его на работу:

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

  2. В логике, которая выполняет изменение данных, убедитесь, что он обновляет один и тот же список экземпляр, что активность передается адаптеру

  3. Затем вызова .notifyDataSetChanged(); работал

Помните, что позиция ListView начинается с 1, так что вам придется делать (listViewPosition - 1) для ваших вашего java.util.List

3

Это может быть стоит проверить, если у вас есть пустое переопределение для registerDataSetObserver(). Android Studio добавила один для меня, не выполняя вызов супер. Добавление его в так было достаточно, чтобы получить мой ListView снова работает:

@Override 
    public void registerDataSetObserver(DataSetObserver observer) { 
     super.registerDataSetObserver(observer);  
    } 
0

Я не имею много репутации комментировать г Hissain answer.It является правильным, но я хочу упомянуть еще одну вещь, что ссылка на список не должны меняться. Если базовый источник данных изменяется, не изменяйте ссылку на новый список. Действия должны выполняться только в том же объекте списка. Чтобы сделать то же самое, очистите список, используя clear(), а затем добавьте данные в тот же список, используя add() или addALL(), а затем вызовите notifyDataSetChanged(). например. На первой инициализации списка

list = dataSource.getList(); 

затем можно добавлять и удалять содержимое из списка и позвонить notifyDataSetChanged() работает нормально, но если в коде, один пытается изменить ссылку на другой объект. Как

list = dataSource.getList(); 

где GetList() возвращает новый список каждый раз, следовательно, ссылки на изменения в какой-либо другой объект списка и призывающую notifyDataSetChnaged не влияет на list.But если GetList() возвращает тот же объект списка, работает отлично.

0

Функция обновления должна вызываться из потока пользовательского интерфейса. Отвечу на самом деле похож на @ user1621629-х answer с той разницей, что я использую rxJava, так вот рабочий код, который решает эту проблему для меня:

this.subscriber = myAdapter.getSubscriber(); // keep for unsubscribe in destroy 
dataSource.subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()).subscribe(this.subscriber); 

Итак, я все исполнения, чтобы получить данные для списка к потоку вычислений, но показывая результат в потоке пользовательского интерфейса.

Вот как я создаю подписчика для этого:

public class MyListAdapter extends RecyclerView.Adapter<LocationListAdapter.ViewHolder> { 


private List<ListItem> mDataset = new ArrayList<>(); 

public Subscriber<ListItem[]> getSubscriber() { 
    return Subscribers.create(new Action1<ListItem[]>() { 
     @Override 
     public void call(ListItem[] listItems) { 
      mDataset.clear(); 
      mDataset.addAll(Arrays.asList(listItems)); 
      notifyDataSetChanged(); 
     } 
    }); 
} 
...... 
Смежные вопросы