我有一个主要活动,它将从url异步中获取
JSON数据
这是MainActivity.java
public class MainActivity extends FragmentActivity implements ActionBar.TabListener{ private ViewPager viewPager; private TabsPagerAdapter mAdapter; private ActionBar actionBar; //Tab titles private String[] tabs = {"Sermons","More"}; private String[] sermonsList = new String[0]; //JSON URL for sermonList data private static String sermonListJSONUrl = "https://dl.dropBoxusercontent.com/u/12345/index.PHP"; //Variable to save JSON Object private static final String JSON_KEY_SERMONS = "sermon"; private JSONObject sermonListJSONObject = null; private JSONArray sermonListJSONArray = null; SermonsFragment mSermonFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //Call JSONParser Asynchronously to get sermonList in JSON Format new callJSONParserAsync().execute(sermonListJSONUrl); //this.mSermonFragment = (SermonsFragment) getFragmentManager().findFragmentById(android.R.id.list); this.mSermonFragment = (SermonsFragment) getFragmentManager().findFragmentById(R.id.pager); //Initialization viewPager = (ViewPager) findViewById(R.id.pager); actionBar = getActionBar(); mAdapter = new TabsPagerAdapter(getFragmentManager()); viewPager.setAdapter(mAdapter); actionBar.setHomeButtonEnabled(false); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); //Adding Tabs for(String tab_name : tabs) { actionBar.addTab(actionBar.newTab().setText(tab_name).setTabListener(this)); } /** * on swiping the viewpager make respective tab selected */ viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position,float positionOffset,int positionOffsetPixels) { } @Override public void onPageSelected(int position) { //on changing the page //make respected tab selected actionBar.setSelectedNavigationItem(position); } @Override public void onPageScrollStateChanged(int state) { } }); }
这是activity_main.xml
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v4.view.ViewPager>
这是SermonsFragment.java
public class SermonsFragment extends ListFragment { private String[] sermonsList; ArrayAdapter listAdapter; String imageUrl = "https://fbcdn-sphotos-b-a.akamaihd.net/" + "hphotos-ak-prn2/t1.0-9/10415605_10132423542_6220704573655530117_n.jpg"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); sermonsList = ((MainActivity)getActivity()).getSermonsList(); //ListView for the sermon list,only show if there is something in listview listAdapter = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_1,sermonsList); if(listAdapter.getCount() != 0) { setListAdapter(listAdapter); } } @Override public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_sermons,container,false); // show The Image new getSermonBannerImage((ImageView) rootView.findViewById(R.id.series_banner)) .execute(imageUrl); return rootView; } public void updateListView(String[] newData) { if(newData.length == 0) { Log.d("myTesting3","sermonsList is Empty"); } else { Log.d("myTestingSermonFragment",newData[0]); Log.d("myTestingSermonFragment",newData[1]); } sermonsList = newData; Log.d("myTestingSermonFragment",sermonsList[1]); this.listAdapter.clear(); this.listAdapter.addAll(newData); this.listAdapter.notifyDataSetChanged(); }
这是fragment_sermon.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#222222" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical"> <!-- Shows an image from your drawable resources --> <ImageView android:id="@+id/series_banner" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center" android:src="@drawable/series_banner" /> <!-- Closing tag for the horizontal nested layout --> <View android:layout_width="fill_parent" android:layout_height="10dp" android:layout_marginBottom="10dp" android:background="@android:color/darker_gray"/> <ListView android:id="@android:id/list" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#ffffffff" /> <TextView android:id="@android:id/empty" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:text="No Data" /> </LinearLayout> </RelativeLayout>
这是TabsPagerAdapter.java
public class TabsPagerAdapter extends FragmentPagerAdapter { public TabsPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int index) { switch (index) { case 0: //Sermons fragment activity return new SermonsFragment(); case 1: //More fragment activity return new MoreFragment(); } return null; } @Override public int getCount() { //get item count - equal to number of tabs return 2; } }
最后这是错误
07-27 16:42:27.921 1549-1555/org.myapp.myapp E/jdwp﹕ Failed writing handshake bytes: Broken pipe (-1 of 14) 07-27 16:42:29.941 1549-1549/org.myapp.myapp E/OpenGLRenderer﹕ Getting MAX_TEXTURE_SIZE from GradienCache 07-27 16:42:29.941 1549-1549/org.myapp.myapp E/OpenGLRenderer﹕ MAX_TEXTURE_SIZE: 16384 07-27 16:42:29.953 1549-1549/org.myapp.myapp E/OpenGLRenderer﹕ Getting MAX_TEXTURE_SIZE from Caches::initConstraints() 07-27 16:42:29.953 1549-1549/org.myapp.myapp E/OpenGLRenderer﹕ MAX_TEXTURE_SIZE: 16384 07-27 16:42:30.353 1549-1549/org.myapp.myapp E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: org.myapp.myapp,PID: 1549 java.lang.NullPointerException at org.myapp.myapp.MainActivity$callJSONParserAsync.onPostExecute(MainActivity.java:174) at org.myapp.myapp.MainActivity$callJSONParserAsync.onPostExecute(MainActivity.java:157) at android.os.AsyncTask.finish(AsyncTask.java:632) at android.os.AsyncTask.access$600(AsyncTask.java:177) at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5017) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595) at dalvik.system.NativeStart.main(Native Method)
我不确定为什么会出现OpenGLRenderer错误,但是自从我创建这个应用程序以来它一直存在并运行得很好,所以这不是问题(尽管如果你能指出如何解决这个问题会很棒). MainActivity.java:174是mSermonFragment.updateListView(sermonsList)上的这一行;
我怎样才能确保它正确填充?最好是异步,因此它不会锁定UI,可能是在异步完成后更新listview.
如果你也可以指出,如果在异步期间如何制作它会很好,它将检查是否有互联网连接,列表视图将显示加载圈,如果它没有互联网,或者空列表它将显示否数据,否则会显示清单
解决方法
由于您只有两个片段,因此可以跟踪它们保存实例.使用回调建议它不是最好的选择.
所以,在你的寻呼机适配器中:
public class TabsPagerAdapter extends FragmentPagerAdapter { SermonsFragment mSermonsFragment; MoreFragment mMoreFragment; public TabsPagerAdapter(FragmentManager fm) { super(fm); this.mSermonsFragment = new SermonsFragment(); this.mMoreFragment = new MoreFragment(); } @Override public Fragment getItem(int index) { switch (index) { case 0: //Sermons fragment activity return mSermonsFragment; case 1: //More fragment activity return mMoreFragment; } return null; } @Override public int getCount() { //get item count - equal to number of tabs return 2; } public updateSermonsFragment(String[] data) { mSermonsFragment.updateData(data); } //i don't know what's the data type managed by MoreFragment public updateMoreFragment(Object data) { mMoreFragment.updateData(data) } }
创建一个方法来更新片段中的适配器:
public void updateData(String[] newData) { this.listAdapter.clear(); for(int i = 0; i < newData.length; i++) { this.listAdapter.add(newData[i]); } this.listAdapter.notifyDataSetChanged(); }
然后你可以从你的适配器方法的AsyncTask的onPostExecute中调用这个方法:
protected void onPostExecute(JSONObject jsonObject) { sermonListJSONObject = jsonObject; sermonListJSONArray = parseJSONObjToJSONArray(sermonListJSONObject,JSON_KEY_SERMONS); String[] sermonsList; .... // here you need set an array with the strings you parsed //here you call the new method on the adapter to update your data. mAdapter.updateSermonsFragment(sermonsList); }
另一个最佳实践是在片段中定义静态newInstace(String []数据)方法,这样您就可以在第一次网络调用时初始化片段数据,以确保您的片段有一个数据集可以使用,然后如上所述进行更新.