在填充的ListView片段从异步完成活动后, [英] Populate ListView on Fragment after Async done from Activity
问题描述
我主要活动,将得到一个网址异步JSON数据
I have main activity which will get JSON data from a url async
这是MainActivity.java
This is 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中
This is 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
This is 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
This is 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
This is 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);
我怎样才能确保它是正确填充? preferably异步所以它不会锁定用户界面,可能是由后来经过更新列表视图异步完成。
How can I make sure it is populate correctly? preferably async so it's not locking the UI, maybe by updating the listview later after async complete.
这将是很好,如果你也可以指出的是,如何让这么异步过程中,它会检查是否有互联网连接,列表将显示加载圈,如果没有互联网,或空列表它将不显示数据,否则会显示列表
It would be nice, if you could also point out, how to make it so during async, it will check if there's internet connection, the list view will show loading circle, and if it has no internet, or empty list it will show no data, otherwise it will show the list
推荐答案
既然你只有两个片段,您可以跟踪他们的保存情况。使用回调的建议是不是最好的选择。
Since you only have two fragments, you can keep track of them saving the instances. Using callbacks as suggested it's not the best option.
那么,在您的寻呼机适配器:
So, in your pager adapter:
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)
}
}
创建一个方法,在你的片段来更新您的适配器:
Create a method to update your adapter in your fragment:
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 trought的onPostExecute调用此方法适配器方法:
Then you can call this method from the onPostExecute of your AsyncTask trought your adapter method:
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(字符串[]数据)
方法,这样你就可以在第一个网络调用初始化片段数据的另一种最佳实践,以确保您的片段有一个数据集与如上所述然后更新工作。
Another best practice it's to define a static newInstace(String[] data)
method in your fragment, so you can initialize the fragment data at the very first network call, to be sure your fragment has a dataset to work with then update as described above.
这篇关于在填充的ListView片段从异步完成活动后,的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!