片段的所有组件都返回null

时间:2016-12-21 18:14:27

标签: android android-layout android-fragments nullpointerexception

好的,所以我尝试传递一个JSON对象,使用putExtra属性将字符串转换为另一个意图。然后下面的代码触发启动我试图添加片段的活动。但是,在尝试加载该活动时,应用程序崩溃,表示正在对空对象强制转换方法。需要帮助。

这是触发活动的代码:

detailsField[i].setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    Intent intent = new Intent(getContext() , DetailActivity.class);
                    intent.putExtra("jsonStr" , J.toString());
                    startActivity(intent);
                }
            });

这里是DetailActivity.java类:

public class DetailActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    //getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    setContentView(R.layout.activity_detail);
    DetailFragment hello = new DetailFragment();
    getSupportFragmentManager().beginTransaction().add(R.id.fragment_detail, hello, "HELLO").commit();
    }
}

以下是片段内的方法:

public void updateView() {
    try {
        obj = new JSONObject(intent.getStringExtra("jsonStr"));
        setWeatherIcon();
        humidityIcon.setText(getActivity().getString(R.string.humidity_icon));
        sunsetIcon.setText(getActivity().getString(R.string.sunset_icon));
        sunriseIcon.setText(getActivity().getString(R.string.sunrise_icon));
        speedIcon.setText(getActivity().getString(R.string.speed_icon));
        pressureIcon.setText(getActivity().getString(R.string.pressure_icon));

        Long date1 = obj.getLong("dt");
        Date expiry = new Date(Long.parseLong(Long.toString(date1)) * 1000);
        String date = new SimpleDateFormat("EE, dd" , Locale.US).format(expiry);
        dateText.setText(date);

        long dy = obj.getJSONObject("main").getLong("day");
        int day = (int) dy;
        sunriseText.setText("Day : " + day + getString(R.string.c));

        long nt = obj.getJSONObject("main").getLong("night");
        int night = (int) nt;
        sunsetText.setText("Night : " + night + getString(R.string.c));

        SpannableString ss1=  new SpannableString(date + "\n"
                + obj.getJSONObject("temp").getLong("max") + "°" + "      "
                + obj.getJSONObject("temp").getLong("min") + "°" + "\n");
        ss1.setSpan(new RelativeSizeSpan(1.1f), 0,7, 0); // set size
        ss1.setSpan(new RelativeSizeSpan(1.4f) , 8 , 11 , 0);
        tempText.setText(ss1);

        humidityText.setText(obj.getInt("humidity") + "%");
        speedText.setText(obj.getLong("speed") + " km/h");
        pressureText.setText(obj.getLong("pressure") + " hPa");
    }
    catch (JSONException ex) {
        Log.e("Detail View" , "Cannot Find Details");
        getActivity().finish();
    }
}

private void setWeatherIcon() throws JSONException {
    int id = obj.getJSONArray("weather").getJSONObject(0).getInt("id");
    String icon = "";
    switch(id) {
        /*Many Switch Cases above which do not cause problem*/
        case 900 :
        case 781 : icon = getActivity().getString(R.string.weather_tornado);
            break;
        case 904 :
        case 800 : icon = getActivity().getString(R.string.weather_sunny);
            break;
        case 801 :
        case 802 :
        /*Many Switch Cases below which do not cause problem*/
    }
    weatherIcon.setText(icon);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_detail, container, false);
    cityField = (TextView) rootView.findViewById(R.id.city_field);
    dateText = (TextView) rootView.findViewById(R.id.date_text);

    weatherIcon = (TextView) rootView.findViewById(R.id.weather_icon);
    weatherIcon.setTypeface(weatherFont);
    tempText = (TextView) rootView.findViewById(R.id.temp_text);

    humidityIcon = (TextView) rootView.findViewById(R.id.humidity_icon);
    humidityIcon.setTypeface(weatherFont);
    humidityText = (TextView) rootView.findViewById(R.id.humidity_text);
    speedIcon = (TextView) rootView.findViewById(R.id.speed_icon);
    speedIcon.setTypeface(weatherFont);
    speedText = (TextView) rootView.findViewById(R.id.speed_text);
    pressureIcon = (TextView) rootView.findViewById(R.id.pressure_icon);
    pressureIcon.setTypeface(weatherFont);
    pressureText = (TextView) rootView.findViewById(R.id.pressure_text);

    sunriseIcon = (TextView) rootView.findViewById(R.id.sunrise_icon);
    sunriseIcon.setTypeface(weatherFont);
    sunriseText = (TextView) rootView.findViewById(R.id.sunrise_text);
    sunsetIcon = (TextView) rootView.findViewById(R.id.sunset_icon);
    sunsetIcon.setTypeface(weatherFont);
    sunsetText = (TextView) rootView.findViewById(R.id.sunset_text);

    return rootView;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    weatherFont = Typeface.createFromAsset(getActivity().getAssets(), "fonts/newweather.ttf");
    intent = getActivity().getIntent();
    updateView();
}

这里是activity_detail.xml文件,用于DetailActivity

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.a5corp.weather.DetailActivity">

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay" />

</android.support.design.widget.AppBarLayout>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/fragment_detail"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.a5corp.weather.WeatherActivity"
    tools:ignore="MergeRootFrame"
    android:background="@color/colorPrimary" />

</android.support.design.widget.CoordinatorLayout>

我不知道我是否应该提供片段xml,因为我的片段定义得很好。

以下是错误消息:

12-21 23:33:23.777 13286-13286/com.a5corp.weather E/AndroidRuntime: FATAL EXCEPTION: main
                                                                Process: com.a5corp.weather, PID: 13286
                                                                java.lang.RuntimeException: Unable to start activity ComponentInfo{com.a5corp.weather/com.a5corp.weather.DetailActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
                                                                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2423)
                                                                    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2483)
                                                                    at android.app.ActivityThread.access$900(ActivityThread.java:153)
                                                                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1349)
                                                                    at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                    at android.os.Looper.loop(Looper.java:148)
                                                                    at android.app.ActivityThread.main(ActivityThread.java:5441)
                                                                    at java.lang.reflect.Method.invoke(Native Method)
                                                                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738)
                                                                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)
                                                                 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
                                                                    at com.a5corp.weather.DetailFragment.setWeatherIcon(DetailFragment.java:157)
                                                                    at com.a5corp.weather.DetailFragment.updateView(DetailFragment.java:37)
                                                                    at com.a5corp.weather.DetailFragment.onCreate(DetailFragment.java:196)
                                                                    at android.support.v4.app.Fragment.performCreate(Fragment.java:2075)
                                                                    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1060)
                                                                    at android.support.v4.app.BackStackRecord.setLastIn(BackStackRecord.java:838)
                                                                    at android.support.v4.app.BackStackRecord.calculateFragments(BackStackRecord.java:861)
                                                                    at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:719)
                                                                    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1682)
                                                                    at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:388)
                                                                    at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:607)
                                                                    at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:181)
                                                                    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1238)
                                                                    at android.app.Activity.performStart(Activity.java:6320)
                                                                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2386)
                                                                    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2483) 
                                                                    at android.app.ActivityThread.access$900(ActivityThread.java:153) 
                                                                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1349) 
                                                                    at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                    at android.os.Looper.loop(Looper.java:148) 
                                                                    at android.app.ActivityThread.main(ActivityThread.java:5441) 
                                                                    at java.lang.reflect.Method.invoke(Native Method) 
                                                                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738) 
                                                                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628) 

(片段中的第157行是setWeatherIcon()函数中的weatherIcon.setText(icon)

第37行是在Fragment的updateView()中调用的setWeatherIcon()

第96行是在Fragment&#39; onCreate()中调用的updateView())

(即使我注释掉了这行,它为另一个TextView提供了相同的NullPointerException,注释那个也为另一个TextView提供了另一个NullPointerException)

3 个答案:

答案 0 :(得分:2)

根据片段生命周期,onCreate()是第一个被调用的方法。但是视图是在onCreateView函数中生成和初始化的。因此,在初始化onCreate函数之前,您要在UI元素中设置值。

updateView()方法移除调用onCreate()并将其放入onCreateView函数中。

答案 1 :(得分:0)

片段与活动

的生命周期不同
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //  updateView(); There is no view yet... All Views are null
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_detail, container, false);
    cityField = (TextView) rootView.findViewById(R.id.city_field);
    dateText = (TextView) rootView.findViewById(R.id.date_text);

    ...

    // Now there are some views (assuming the XML is correct)

    return rootView;
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    // Now there are definitely some views (again, same assumptions)
}

因此,在分配视图后,您必须致电updateView

片段使用getArguments()来获取额外内容。不确定为什么需要intent = getActivity().getIntent();

答案 2 :(得分:0)

@rahulkapoor有你崩溃的确切解决方案。

我在这里回答是为了清除从ActivityFragment传递参数的想法。你做错了。

因此,您启动了DetailsActivity并传递了一些intent。您需要首先在onCreate的{​​{1}}函数中获取intent中的额外内容。

然后,在从DetailsActivity的{​​{1}}函数启动Fragment之前,您需要将信息作为参数传递给启动onCreate

DetailsActivity

现在,在Fragment的{​​{1}}函数中,您需要获取参数并相应地更新您的视图。您可以从public class DetailActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); setContentView(R.layout.activity_detail); // Now set the arguments in your launching fragment. DetailFragment hello = new DetailFragment(); hello.setArguments(getIntent().getExtras()); // Now launch the Fragment. getSupportFragmentManager().beginTransaction().add(R.id.fragment_detail, hello, "HELLO").commit(); } } 删除onCreateView功能。

Fragment