0

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

import java.util.ArrayList; 

import org.json.JSONArray; 
import org.json.JSONException; 

import android.app.ListFragment; 
import android.app.ProgressDialog; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ArrayAdapter; 

public class BlogFragment extends ListFragment { 

    String[] countries = new String[] { 
     "India", 
     "Pakistan", 
     "Sri Lanka", 
     "China", 
     "Bangladesh", 
     "Nepal", 
     "Afghanistan", 
     "North Korea", 
     "South Korea", 
     "Japan" 
    }; 

    String [] titles ={}; 
    ArrayAdapter<String> adapter; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { 
     /** Creating an array adapter to store the list of countries **/ 
     new AsyncFetchData().execute(); 
     adapter = new ArrayAdapter<String>(inflater.getContext(), android.R.layout.simple_list_item_1,titles); 

     return super.onCreateView(inflater, container, savedInstanceState); 
    } 

    private class AsyncFetchData extends AsyncTask 
    { 

     @Override 
     protected Object doInBackground(Object... arg0) { 


      JSONArray a = new JSONArray(); 
      ArrayList<String> aList = new ArrayList<String>(); 
      a = ServerAPI.getData(); 
      for (int i = 0; i < a.length(); i++) { 
       String title = null; 
       String content = null; 
       try { 
        title = a.getJSONObject(i).getString("title"); 
        content = a.getJSONObject(i).getString("content"); 
        aList.add(title); 
       } catch (JSONException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
       System.out.println(title); 
//    System.out.println(content); 
      } 
      titles = aList.toArray(new String[aList.size()]); 
      /** Setting the list adapter for the ListFragment */ 


      return null; 
     } 

     protected void onPostExecute(Object result) { 
     // TODO Auto-generated method stub 
     ArrayAdapter aa = new ArrayAdapter(getActivity().getBaseContext(), android.R.layout.simple_list_item_1, titles); 
     aa.notifyDataSetChanged(); 
     setListAdapter(aa); 
    } 
    } 
} 

Строка массива countries отображается правильно в методе runOnUiThread, а названия нет. Я проверяю данные, помещенные в массив строк заголовков, и он действителен. Любая идея, почему это происходит?

+0

Пробовал ли вы 'adapter.notifyDatasetChanged()' перед вызовом setListAdapter'? –

+0

@MysticMagic ничего не происходит. – omarsafwany

+0

Затем вызовите listView.invalidateViews(); сразу после notifyDatasetChanged –

ответ

0

Проблема заключается в том:

Ваш адаптер уже был инициализирован со старым набором данных. Таким образом, вы обновляете базовые данные, но адаптер все еще хранит старые данные.

Необходимо обновить адаптер новыми данными.

Для этого

вызов

adapter.notifyDatasetChanged(); 

непосредственно перед

setListAdapter(adapter); 

notifyDataSetChanged: Уведомляет присоединенные наблюдателей, что основные данные были изменены и любой вид, отражающий данные набор должен обновляться.

+0

Я сделал, как вы сказали, но ничего не происходит. – omarsafwany

0

Сначала создайте новый адаптер для новых заголовков, а затем установите этот адаптер.

0

Есть несколько странных вещей, которые я вижу в вашем коде:.

  1. В onCreateView вы начинаете новый AsyncFetchData() Execute(). Это может быть полезно, если хочет, чтобы загрузить данные для текущего элемента списка, для всего списка это сделано по-другому (не внутри onCreateView)

  2. Я ожидал бы onCreateView создать новый вид вместо вызова super.onCreateView, чтобы получить доступ к просмотру элементов (и заполнить их с загруженными данными)

Стандартная схема использования ListFragment является:

public class MyListFragment extends ListFragment { 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 
    String[] values = new String[] { "Android", "iPhone", "WindowsMobile", 
     "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X", 
     "Linux", "OS/2" }; 
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), 
     android.R.layout.simple_list_item_1, values); 
    setListAdapter(adapter); 
    } 

} 

Если вы хотите, чтобы обновить список с загруженные данные от AsyncTask, тогда вы должны обновлять данные в массиве, к которому относится адаптер, без повторного создания самого адаптера. И позвоните adapter.notifyDataChanged(), как только будут готовы новые данные, в потоке пользовательского интерфейса (как вы пытаетесь сделать, но обычно это делается в AsyncTask.postExecute(), который был специально разработан для этого случая.

Я думаю, у вас нет данных для показа, прежде чем они будут загружены. Тогда вам не нужно показывать пустой список, может быть какой-то индикатор выполнения.Это может быть TextView «Подождите, загрузите ...» Когда загрузка закончится, вы замените TextView на ListView (или фрагмент), может быть с анимацией. Таким образом, ListView будет создан сразу, и вам не нужно заботиться о его асинхронной загрузке.

ДОБАВЛЕНО: О прогресс бар - это будет лучше использовать стандартные один:

ProgressDialog progress = new ProgressDialog(this); 
progress.setMessage("Please wait, downloading..."); 
progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
progress.setIndeterminate(true); 

AsyncTask.onPreExecute() хорошее место для него. Не забудьте удалить его в onPostExecute()

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