【发布时间】:2014-08-28 07:20:33
【问题描述】:
[我的情况]
现在在 MainActivity 中,我创建了一些片段,其中有一些 TextView。在 MainActivity 中有一个异步线程 AsyncTask 用于从 web 获取信息。 AsyncTask获取完成后会通过回调方法更新上述TextViews中的文本(Fragment实现了一个OnInfoGotInterface并在接口中实例化一个onInfoGot()方法。onInfoGot()会调用Fragment中定义的方法setTextView()更新信息)。
[我的问题]
在执行程序时,我发现AsyncTask 完成从web 获取信息的时间点早于Fragment 调用onCreateView() 的时间点。换句话说,当 AsyncTask 调用 (OnInfoGotInterface)fragment.onInfoGot() 设置 TextViews 时,TextViews 还没有被实例化(TextViews 在 CreateView() 上通过 rootView.findViewById() 方法实例化)。结果,出现了 NullPointerException。
[我需要一个解决方案]
现在我想做这样的事情:当 AsyncTask 完成从 web 获取信息并要调用 onInfoGot() 时,我们停止它,并让它等到 Fragment 完成 onCreateView()。之后我们唤醒 AsyncTask 并允许它更新片段。
附言。有人建议我应该在 Fragment 的定义中的 onCreateView() 之后调用 new AsyncTask.excute()。但是这里 AsyncTask 和 Fragment 都是在 MainActivity 中创建的。它们是 MainActivity 中的两个不同的任务线程,一个用于显示数据,另一个用于从 Web 获取数据。
谁能给点建议?我真的很感激! 代码如下:
MainActivity.java:
public class MainActivity extends Activity{
private List<City> cityList;
private ViewPager mPager; /*ViewPager for show the page of city info*/
private ScreenSlidePagerAdapter mPagerAdapter; /* Adapter for the ViewPager,
* ScreenSlidePagerAdapter is a subclass of FragmentStatePagerAdapter*/
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_city);
cityList = new ArrayList<City>();
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
init();
}
private void init(){
loadCities(); //Load cities from database into cityList
initFragments();
getCityInfo();
}
private void initFragments(){
mPagerAdapter.removeAllFragments();
for(City city: cityList){
PageFragment fragment = new PageFragment(city.getName());
mPagerAdapter.addFragment(fragment);
mPagerAdapter.notifyDataSetChanged();
}
}
private void getCityInfo(){
for(City city: cityList){
String cityName = city.getName();
obtainCityInfo(cityName);
}
}
private obtainCityInfo(String cityName){
String request = "http://example.abc.com/"
+ cityName + "&output=json";
new AccessWebServiceTask().execute(request, cityName);
}
private class AccessWebServiceTask extends AsyncTask<String, Void, CityInfo>{
@Override
protected CityInfo doInBackground(String... urls) {
String result = getWebContent(urls[0]); /*Access web through HTTP*/
String cityName = urls[1];
/*Transform the String result to a CityInfo object containing information of a city*/
CityInfo cityInfo = encodeJason(result, cityName);
return cityInfo;
}
protected void onPostExecute(CityInfo cityInfo){
OnCityGot(cityInfo);
}
}
public void onCityGot(CityInfo cityInfo){
if(cityInfo != null){
String cityName = cityInfo.getCityName();
/*Set the info field of a city object*/
cityList.getByName(cityName).setCityInfo(cityInfo);
mPagerAdapter.updateFragment(cityInfo);
}
}
}
ScreenSlidePagerAdapter.java
public class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter{
private List<PageFragment> fragmentsList;
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
fragmentsList = new ArrayList<PageFragment>();
}
public ScreenSlidePagerAdapter(FragmentManager fm, List<PageFragment> list){
super(fm);
fragmentsList = list;
}
@Override
public PageFragment getItem(int position) {
return fragmentsList.get(position);
}
@Override
public int getCount() {
return fragmentsList.size();
}
public void setFragmentsList(List<PageFragment> fragmentsList){
this.fragmentsList = fragmentsList;
notifyDataSetChanged();
}
public void addFragment(PageFragment f){
fragmentsList.add(f);
notifyDataSetChanged();
}
public void removeFragment(int position){
fragmentsList.remove(position);
notifyDataSetChanged();
}
public void removeAllFragments(){
fragmentsList.clear();
notifyDataSetChanged();
}
private PageFragment findFragmentByName(String cityName){
for(PageFragment fragment: fragmentsList){
if(fragment.getCityName().equals(cityName))
return fragment;
}
return null;
}
public void updateFragment(CityInfo cityInfo){
String cityName = cityInfo.getCityName();
OnCityInfoChanged fragment = (OnCityInfoChanged)findFragmentByName(cityName);
String population = cityInfo.getPopulation();
fragment.onCityInfoChanged(population);
notifyDataSetChanged();
}
}
PageFragment.java:
public class PageFragment extends Fragment implements OnCityInfoChanged{
private TextView cityNameText;
private TextView populationText;
String cityName;
String population;
public PageFragment(){}
public PageFragment(String cityName, String population){
this.cityName = cityName;
this.population = population
}
public PageFragment(CityInfo cityInfo){
this.cityName = cityInfo.getCityName();
this.population = cityInfo.getPopulation();
}
public PageFragment(String cityName){
this.cityName = cityName;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState){
ViewGroup rootView = (ViewGroup) inflater.inflate(
R.layout.fragment_city_page2, container, false);
cityNameText = (TextView)rootView.findViewById(R.id.city_name);
populationText = (TextView)rootView.findViewById(R.id.population);
setCityName(cityName);
setPopulation(population)
return rootView;
}
public void setCityName(String name){
cityNameText.setText(name);
}
public void setPopulation(String population){
populationText.setText(population);
}
public String getCityName(){
return cityName;
}
@Override
public void onCityInfoChanged(String population) {
//setCityName(cityName);
setPopulation();
}
}
【问题讨论】:
-
发布代码。当用英语解释时,很难理解发生了什么。
-
我发布了代码。请检查一下。谢谢!
标签: android multithreading android-fragments android-asynctask