具有TextView的setText中的NPE与片段内的onPostExecute中的AsyncTask

时间:2014-05-26 16:30:24

标签: android android-fragments android-asynctask nullpointerexception

我遇到了问题:我正在开发一个Android应用程序,我必须解析一些信息。我正在使用AsyncTask从URL解析信息,我已成功解析了一些信息并在方法onPostExecute()中我调用一个方法,在TextView中显示解析的信息,该信息将显示在片段中。我的应用程序由Fragments分隔,但每次运行我的应用程序时,我都会在我在TextView中设置名为title的文本行中获得NullPointerException。 在onPostExecute中,我调用方法displayText(),在此方法中,我更新了title变量。这是代码的一部分,因此您可以轻松理解:

这是片段

public class WeatherActivity extends Fragment{

TextView title;


public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){
    super.onCreateView(inflater, container, savedInstanceState);
    View view=inflater.inflate(R.layout.weather_activity, container,false);
    title=(TextView)view.findViewById(R.id.weatherTitle);
    return view;
}

public void displayWeather(Weather weather){
    title.setText(weather.getTitle());//this is the line that gives me the NPE
}
}

这是进行解析的类

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

public static final String WEATHER_URL="some url";
Weather weather;
WeatherActivity wa=new WeatherActivity();
@Override
protected Void doInBackground(Void... params) {
    loadXML();//does the parsing
    return null;
}

 protected void onPostExecute(Void result) {
    wa.displayWeather(weather);//calls to update fragment
}

public void loadXML(){
    //does all the work and returns the info in an object weather
}

}

这是我的xml。目前,我只有一个TextView

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

<TextView
    android:id="@+id/weatherTitle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:textAppearance="?android:attr/textAppearanceLarge" />

这是我的LogCat

E/AndroidRuntime(27441): FATAL EXCEPTION: main
E/AndroidRuntime(27441): Process: com.example.test23, PID: 27441
E/AndroidRuntime(27441): java.lang.NullPointerException
E/AndroidRuntime(27441):    at com.example.test23.WeatherActivity.displayWeather(WeatherActivity.java:25)
E/AndroidRuntime(27441):    at com.example.test23.WeatherManager.onPostExecute(WeatherManager.java:30)
E/AndroidRuntime(27441):    at com.example.test23.WeatherManager.onPostExecute(WeatherManager.java:1)

修改 这是我的MainActivity,用于创建标签/片段

public class MainActivity extends FragmentActivity{
    private String tabs[]={"Some String that will display the name of the tabs"};
    ViewPager viewPager=null;
    FragmentManager fragmentManager=getSupportFragmentManager();
    AdapterView adapterView;
    private Fragment fragment;
    private Activity activity;
    static List<Item> news=new ArrayList<Item>();
    ArrayList<Item> sports=new ArrayList<Item>();
    ArrayList<Item> articles=new ArrayList<Item>();
    public static final int TIME_ENTRY_REQUEST_CODE=1;
        static ParseManager parser=new ParseManager();
    JSONManager jmanager=new JSONManager();
    WeatherManager weather=new WeatherManager();

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@SuppressLint("NewApi")

@Override

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    viewPager=(ViewPager)findViewById(R.id.pager);
    viewPager.setAdapter(new AdapterView(fragmentManager));
    viewPager.setOffscreenPageLimit(6);
    adapterView=new AdapterView(getSupportFragmentManager());
    final android.app.ActionBar actionbar=getActionBar();
    ColorDrawable color=new ColorDrawable(Color.parseColor("#cd853f"));
    actionbar.setBackgroundDrawable(color);

    actionbar.setTitle("App title");
    ActionBar.TabListener tabListener=new ActionBar.TabListener() {
        @Override
        public void onTabUnselected(Tab tab, FragmentTransaction ft) {

        }


        @Override
        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            viewPager.setCurrentItem(tab.getPosition());

        }

        @Override
        public void onTabReselected(Tab tab, FragmentTransaction ft) {  

        }
    };
    /*Displaying Tabs for the app */
    for(int i=0;i<tabs.length;i++)          actionbar.addTab(actionbar.newTab().setText(tabs[i]).setTabListener(tabListener));
    actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            actionbar.setSelectedNavigationItem(position);
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {
        }
    });
    parser.execute();//Asynctask
    jmanager.execute();
    weather.execute();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

public void onDestroy(){
    super.onDestroy();
}

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.option1:
            Intent intentContact=new Intent(this,SomeClass.class);
            startActivityForResult(intentContact,TIME_ENTRY_REQUEST_CODE);
              return true;
        case R.id.option2:
            Intent intentAbout=new Intent(this,SomeOtherClass.class);
            startActivityForResult(intentAbout,TIME_ENTRY_REQUEST_CODE);
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

public void onRefreshClicked(MenuItem refresh); 
}

}

如有任何帮助,请联系我们。提前谢谢。

2 个答案:

答案 0 :(得分:3)

我看到了几个问题:

1)你不应该通过调用它的构造函数来实例化Fragment。 Android的工作是通过FragmentManager类为您完成。

2)您正在尝试使用wa Fragment变量来调用方法。虽然这在常规Java类中是有意义的。 Fragments有自己的生命周期。此生命周期的一部分是onCreateView()状态。在onCreateView()中,系统希望您扩展要显示的布局。现在,您正在通过调用其构造函数来创建Fragment的实例,之后,您正在调用一个引用尚未膨胀的TextView的方法;因此没有TextView所以它是null

答案 1 :(得分:0)

正如@emmanuel解释的那样,片段内的onCreateView在你的片段被附加到一个活动之前没有被调用。因此,textView未初始化且为null。

在显示片段对象之前,不应该调用任何方法。

FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.your_placehodler, new YourFragment());
ft.commit(); 

调用此行onCreateView后,{}返回的view将显示在您的活动R.id.your_placehodler内。

现在调用displayWeather不会导致NLP。