2015-08-30 5 views
0

Я использую это Tutorial и его sourcecodes, чтобы сделать listview в android. Я реализовал этот учебник, но во время обновления setListAdapter я не могу обновить listview динамически. Я рассмотрел многие вопросы о stackoverflow, и они дают adapter.notifyDataSetChanged() в качестве решения. Но я не могу реализовать его в AsyncTask.Обновление setListAdapter от AsyncTask

ItemListFragment.java

public class ItemListFragment extends ListFragment { 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    View v = super.onCreateView(inflater, container, savedInstanceState); 
    setListAdapter(new ItemAdapter(getActivity(), setArray(getActivity()))); 
    return v; 
} 

public ArrayList<Item> setArray(Context context) 
{ 
    ArrayList<Item> items = new ArrayList<Item>(); 
    Realm realm = Realm.getInstance(context); 
    RealmResults<Books> bs = realm.where(Books.class).findAll(); 
    for (int i = 0; i < bs.size(); i++) { 
     Bitmap url = BitmapFactory.decodeFile(bs.get(i).getCover()); 
     String title = bs.get(i).getName(); 
     String description = bs.get(i).getAuthor(); 
     Item item = new Item(url, title, description); 
     items.add(item); 
    } 
    realm.close(); 
    return items; 
} 
} 

ItemAdapter.java

public class ItemAdapter extends ArrayAdapter<Item> { 

public ItemAdapter(Context context, List<Item> items) { 
    super(context, 0, items); 
} 

public View getView(int position, View convertView, ViewGroup parent) 
{ 
    ItemView itemView = (ItemView) convertView; 
    if (null == itemView) 
    { 
     itemView = ItemView.inflate(parent); 
    } 
    itemView.setItem(getItem(position)); 
    return itemView; 
} 
} 

MainActivity.java

public class MainActivity extends AppCompatActivity { 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_list); 
    if (BuildConfig.DEBUG) 
     ViewServer.get(this).addWindow(this); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.menu_main, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    // Handle action bar item clicks here. The action bar will 
    // automatically handle clicks on the Home/Up button, so long 
    // as you specify a parent activity in AndroidManifest.xml. 
    int id = item.getItemId(); 

    //noinspection SimplifiableIfStatement 
    if (id == R.id.action_settings) { 
     return true; 
    } 
    else if (id == R.id.update) { 
     Update update = new Update(getApplicationContext(), MainActivity.this); 
     update.execute(); 
     return true; 
    } 

    return super.onOptionsItemSelected(item); 
} 

@Override 
protected void onDestroy() { 
    super.onDestroy(); 
    if (BuildConfig.DEBUG) 
     ViewServer.get(this).removeWindow(this); 
} 

@Override 
protected void onResume() { 
    super.onResume(); 
    if (BuildConfig.DEBUG) 
     ViewServer.get(this).setFocusedWindow(this); 
} 
} 

Update.java

public class Update extends AsyncTask<Void,Void,Void>{ 

private Context context; 
public Activity activity; 

public Update(Context context, Activity activity) 
{ 
    this.context = context; 
    this.activity = activity; 
} 

    @Override 
protected Void doInBackground(Void... params) { 
    ServerAddress = context.getString(R.string.ServerAddress); 
    StringExtras = context.getString(R.string.CheckBook); 
    Realm realm = null; 
    try { 
     URL url = new URL(ServerAddress + StringExtras); 
     HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); 
     httpURLConnection.setRequestMethod("GET"); 
     httpURLConnection.setRequestProperty("Content-length", "0"); 
     httpURLConnection.setUseCaches(false); 
     httpURLConnection.setAllowUserInteraction(false); 
     httpURLConnection.setConnectTimeout(1000); 
     httpURLConnection.setReadTimeout(1000); 
     httpURLConnection.connect(); 

     int responseCode = httpURLConnection.getResponseCode(); 
     Log.i("Response Code",responseCode+""); 

     BufferedReader br = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream())); 
     String InputLine; 
     StringBuilder response = new StringBuilder(); 

     while ((InputLine = br.readLine()) != null) 
     { 
      response.append(InputLine); 
     } 
     br.close(); 
     httpURLConnection.disconnect(); 

     Log.i("Response Data", response.toString()); 

     GsonBuilder gsonBuilder = new GsonBuilder(); 
     Gson gson = gsonBuilder.create(); 

     JSONArray array = new JSONArray(response.toString()); 
     //booksList = Arrays.asList(books); 
     //JSONArray jsonArray = object.getJSONArray("cover"); 

     realm = Realm.getInstance(context); 
     for (int i=0; i< array.length(); i++) { 
      JSONObject object = array.getJSONObject(i); 
      Books books = gson.fromJson(object.toString(), Books.class); 
      Publish(books, realm); 
     } 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 
    finally { 
     if (realm != null){ 
      realm.close(); 
     } 
    } 
    return null; 
} 

@Override 
protected void onPostExecute(Void aVoid) { 
    super.onPostExecute(aVoid); 
    //i want to call the setarray that contains my database data which has been updated on `doinbackground` and update the listview accordingly. 
//The below codes are just the codes that i have tried but what should i do to update the listview. 
activity.runOnUiThread(new Runnable() { 
     @TargetApi(Build.VERSION_CODES.HONEYCOMB) 
     @Override 
     public void run() { 
      ItemListFragment activity1 = new ItemListFragment(); 
      ArrayList<Item> arrayList = activity1.setArray(context); 
      List<Item> list = new ArrayList<Item>(); 
      int i = 0; 
      for (Item item : arrayList) 
      { 
       list.add(arrayList.get(i)); 
       i++; 
      } 
      activity1.arrayAdapter.addAll(list); 
      activity1.arrayAdapter.notifyDataSetChanged(); 
     } 
    }); 

    } 

Я пытаюсь обновить ListView из postexcution. Итак, как я могу обновить представление через него.

Ошибка От AsyncTask

просто упаковывают вам нужно, но это не проблема

8-30 16:31:47.976 1167-1167/? E/AndroidRuntime﹕ FATAL EXCEPTION: main 
java.lang.NullPointerException 
     at np.com.thefourthgeneration.Update$1.run(Update.java:124) 
     at android.app.Activity.runOnUiThread(Activity.java:4673) 
     at np.com.thefourthgeneration.Update.onPostExecute(Update.java:108) 
     at np.com.thefourthgeneration.Update.onPostExecute(Update.java:34) 
     at android.os.AsyncTask.finish(AsyncTask.java:631) 
     at android.os.AsyncTask.access$600(AsyncTask.java:177) 
     at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644) 
     at android.os.Handler.dispatchMessage(Handler.java:99) 
     at android.os.Looper.loop(Looper.java:137) 
     at android.app.ActivityThread.main(ActivityThread.java:5103) 
     at java.lang.reflect.Method.invokeNative(Native Method) 
     at java.lang.reflect.Method.invoke(Method.java:525) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
     at dalvik.system.NativeStart.main(Native Method) 
+0

Вам не нужно писать runOnUiThread в методе onPostExecute, потому что onPostExecute работает в основном потоке. Просто вызовите notifyDataSetChanged в onPostExecute. – kolombo

+0

is notifDataSetChanged() не работает для вас? – umerk44

+0

Для чего вы создаете новый экземпляр ItemListFragment? Для чего несколько раз создаем ArrayList? Где размещено обновление класса - в действии? В чем проблема - вы не можете очистить адаптер, или не можете его обновить или выпустить некоторую ошибку? Предоставьте больше кода и будьте конкретны в вопросе. – kolombo

ответ

0

макет/activity_list

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical"> 

    <FrameLayout 
     android:id="@+id/content_frame" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"/> 
</LinearLayout> 

макет/list_fragment

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical"> 

    <ListView 
     android:id="@+id/listView" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content"/> 
</LinearLayout> 

MainActivity

public class MainActivity extends AppCompatActivity 
{ 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_list); 

     FragmentManager fm = getFragmentManager(); 

     itemListFragment = (ItemListFragment) fm.findFragmentByTag(ItemListFragment.class.getSimpleName()); 
     if (itemListFragment == null) { 
      itemListFragment = new ItemListFragment(); 
      FragmentTransaction fragmentTransaction = fm.beginTransaction(); 
      fragmentTransaction.replace(R.id.content_frame, itemListFragment, ItemListFragment.class.getSimpleName()); 
      fragmentTransaction.commit(); 
     } 
     if (BuildConfig.DEBUG) { 
      ViewServer.get(this).addWindow(this); 
     } 
    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     if (BuildConfig.DEBUG) { 
      ViewServer.get(this).removeWindow(this); 
     } 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     if (BuildConfig.DEBUG) { 
      ViewServer.get(this).setFocusedWindow(this); 
     } 
    } 
} 

ItemListFragment

public class ItemListFragment extends Fragment 
{ 
    private ListView listView; 
    private ItemAdapter itemAdapter; 
    private ArrayList<Item> itemArrayList = new ArrayList<>(); 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setRetainInstance(true); 
     setHasOptionsMenu(true); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.list_fragment, container, false); 
     itemAdapter = new ItemAdapter(getActivity(), itemArrayList); 
     listView = (ListView) view.findViewById(R.id.listView); 
     listView.setAdapter(itemAdapter); 
     return view; 
    } 

    @Override 
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
     inflater.inflate(R.menu.menu_main, menu); 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
      case R.id.action_settings: 
       return true; 
      case R.id.update: 
       new Update(getActivity()).execute(); 
       return true; 
      default: 
       return super.onOptionsItemSelected(item); 
     } 

    } 

    public class Update extends AsyncTask<Void, Void, Void> 
    { 
     private Context context; 

     public Update(Context context) { 
      this.context = context; 
     } 

     @Override 
     protected Void doInBackground(Void... params) { 
      ServerAddress = context.getString(R.string.ServerAddress); 
      StringExtras = context.getString(R.string.CheckBook); 
      Realm realm = null; 
      try { 
       URL url = new URL(ServerAddress + StringExtras); 
       HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); 
       httpURLConnection.setRequestMethod("GET"); 
       httpURLConnection.setRequestProperty("Content-length", "0"); 
       httpURLConnection.setUseCaches(false); 
       httpURLConnection.setAllowUserInteraction(false); 
       httpURLConnection.setConnectTimeout(1000); 
       httpURLConnection.setReadTimeout(1000); 
       httpURLConnection.connect(); 

       int responseCode = httpURLConnection.getResponseCode(); 
       Log.i("Response Code", responseCode + ""); 

       BufferedReader br = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream())); 
       String InputLine; 
       StringBuilder response = new StringBuilder(); 

       while ((InputLine = br.readLine()) != null) { 
        response.append(InputLine); 
       } 
       br.close(); 
       httpURLConnection.disconnect(); 

       Log.i("Response Data", response.toString()); 

       GsonBuilder gsonBuilder = new GsonBuilder(); 
       Gson gson = gsonBuilder.create(); 

       JSONArray array = new JSONArray(response.toString()); 
       //booksList = Arrays.asList(books); 
       //JSONArray jsonArray = object.getJSONArray("cover"); 

       realm = Realm.getInstance(context); 
       for (int i = 0; i < array.length(); i++) { 
        JSONObject object = array.getJSONObject(i); 
        Books books = gson.fromJson(object.toString(), Books.class); 
        Publish(books, realm); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } finally { 
       if (realm != null) { 
        realm.close(); 
       } 
      } 
      return null; 
     } 

     @Override 
     protected void onPostExecute(Void aVoid) { 
      itemArrayList.clear(); 
      itemArrayList.addAll(getArray(context)); 
      itemAdapter.notifyDataSetChanged(); 
     } 

     public ArrayList<Item> getArray(Context context) { 
      ArrayList<Item> items = new ArrayList<Item>(); 
      Realm realm = Realm.getInstance(context); 
      RealmResults<Books> bs = realm.where(Books.class).findAll(); 
      for (int i = 0; i < bs.size(); i++) { 
       Bitmap url = BitmapFactory.decodeFile(bs.get(i).getCover()); 
       String title = bs.get(i).getName(); 
       String description = bs.get(i).getAuthor(); 
       Item item = new Item(url, title, description); 
       items.add(item); 
      } 
      realm.close(); 
      return items; 
     } 

    } 

    public class ItemAdapter extends ArrayAdapter<Item> 
    { 

     public ItemAdapter(Context context, List<Item> items) { 
      super(context, 0, items); 
     } 

     public View getView(int position, View convertView, ViewGroup parent) { 
      ItemView itemView = (ItemView) convertView; 
      if (null == itemView) { 
       itemView = ItemView.inflate(parent); 
      } 
      itemView.setItem(getItem(position)); 
      return itemView; 
     } 
    } 
} 

Это не код работы 100%, потому что я не в полной мере понять все структуры (как Realm), и я не проверить его , но его основная идея.

+0

как вы получили доступ к 'itemArrayList'' класса ItemListFragment', который является 'private', можете ли вы объяснить это ? – PaladiN

+0

@PaladiN itemArrayList его частный член ItemListFragment и ItemListFragment имеет полный доступ к itemArrayList. Я переместил весь код в фрагмент - классы обновления и адаптера, помещенные внутри ItemListFragment, а также доступ к закрытым членам внешнего класса (из ItemListFragment). Поэтому вам не нужно ссылаться на Activity или что-то еще - вся работа выполняется в ItemListFragment. Если вам нужно иметь доступ к элементу itemArrayList в других фрагментах, вы можете передать его (itemArrayList) по активности. – kolombo

+0

@PaladiN вы попробовали этот код? Вы пытались это понять? Это полезно для вас? Я пишу этот код, чтобы помочь вам, если вам это действительно нужно. Не для вас просто посмотрите на это и скажите «О, что угодно ...» – kolombo