【问题标题】:Fragment's onCreateView called before activity's onCreate在活动的 onCreate 之前调用 Fragment 的 onCreateView
【发布时间】:2017-08-20 09:24:15
【问题描述】:

我有我的VehicleListActivity,它将Bundle 传递给我的片段。 这是活动的onCreate 方法:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_vehicle_list);
    vehicles = new ArrayList<>();

    Intent intent = getIntent();
    String userID = intent.getStringExtra("userID");
    LoadingVehicleListFragment f = new LoadingVehicleListFragment();
    Bundle fArguments = new Bundle();
    fArguments.putString("userID", userID);
    f.setArguments(fArguments);
    getSupportFragmentManager().beginTransaction().add(R.id.loadingVehicleFragment, f).commit();
}

这是片段的onCreateView

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    activity = (VehicleListActivity)getActivity();
    context = activity;
    listener = activity;
    String userID = getArguments().getString("userID");
    getUserInformation(userID);

    return inflater.inflate(com.devspark.progressfragment.R.layout.fragment_progress, container, false);
}

我注意到片段的onCreateView 在活动的onCreate 之前被调用,所以我的片段中的getArguments() 返回一个空值,这会导致空指针异常。 我应该在我的片段中将getArguments() 放在哪里以避免此异常?

编辑:根据要求,这是整个片段的来源:

public class LoadingVehicleListFragment extends ProgressFragment
{
private VehicleListListener listener;
private VehicleListActivity activity;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    return inflater.inflate(com.devspark.progressfragment.R.layout.fragment_progress, container, false);
}

/*@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState)
{
    super.onActivityCreated(savedInstanceState);
    int c = 0;
    listener = (VehicleListActivity)getActivity();
    getUserInformation(getArguments().getString("userID"));
}*/

private void getUserVehicles(String userID)
{
    Response.Listener<String> responseListener = new Response.Listener<String>()
    {
        @Override
        public void onResponse(String response)
        {
            try
            {
                HashMap resultMap = new ObjectMapper().readValue(response, HashMap.class);
                VehicleListRequest.ErrorCode errorCode = VehicleListRequest.ErrorCode.fromInt(Integer.parseInt(resultMap.get("error_code").toString()));

                switch (errorCode)
                {
                    case NONE:
                        parseVehicleFromMap(resultMap);
                        break;
                    case EXCEPTION_CAUGHT:
                        AlertDialog.Builder builder2 = new AlertDialog.Builder(getActivity());
                        builder2.setMessage("Eccezione catturata. \n Messaggio: " + resultMap.get("error_message"));
                        builder2.create().show();
                        break;
                }
            }
            catch (IOException e)
            {
                // TODO gestire
                e.printStackTrace();
            }
        }
    };

    VehicleListRequest request = new VehicleListRequest(userID, responseListener, null);
    RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
    requestQueue.add(request);
}

public void getUserInformation(final String userID)
{
    Response.Listener<String> responseListener = new Response.Listener<String>()
    {
        @Override
        public void onResponse(String response)
        {
            try
            {
                HashMap resultMap = new ObjectMapper().readValue(response, HashMap.class);
                GetUserRequest.ErrorCode errorCode = GetUserRequest.ErrorCode.fromInt(Integer.parseInt(resultMap.get("error_code").toString()));

                switch (errorCode)
                {
                    case NONE:
                        listener.setLoggedUser(User.fromMap(resultMap));
                        getUserVehicles(userID);
                        break;
                    case EXCEPTION_CAUGHT:
                        AlertDialog.Builder builder2 = new AlertDialog.Builder(getActivity());
                        builder2.setMessage("Eccezione catturata. \n Messaggio: " + resultMap.get("error_message"));
                        builder2.create().show();
                        break;
                }
            }
            catch (IOException e)
            {
                // TODO gestire
                e.printStackTrace();
            }
        }
    };

    GetUserRequest request = new GetUserRequest(userID, responseListener, null);
    RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
    requestQueue.add(request);
}

private void parseVehicleFromMap(HashMap map)
{
    int i = 0;

    while (map.containsKey(String.valueOf(i)))
    {
        final Vehicle v = new Vehicle();
        HashMap vehicleMap = (HashMap) map.get(String.valueOf(i));

        v.setPlate(vehicleMap.get("plate").toString());
        v.setKm(vehicleMap.get("km") == null ? null : Integer.parseInt(vehicleMap.get("km").toString()));
        v.setInUse(Integer.parseInt(vehicleMap.get("in_use").toString()) == 1);
        v.setFuelQuantity(Double.parseDouble(vehicleMap.get("actual_fuel_quantity").toString()));
        v.setEffectiveFuelEconomy(Double.parseDouble(vehicleMap.get("effective_fuel_economy").toString()));
        v.setInsuranceDate(vehicleMap.get("insurance_date") == null ? null : new LocalDate(vehicleMap.get("insurance_date").toString()));
        v.setMatriculationDate(new LocalDate(vehicleMap.get("matriculation_date").toString()));
        v.setLatitude(vehicleMap.get("latitude") == null ? null : Double.parseDouble(vehicleMap.get("latitude").toString()));
        v.setLongitude(vehicleMap.get("longitude") == null ? null : Double.parseDouble(vehicleMap.get("longitude").toString()));
        v.setUser(activity.getLogged());

        listener.addVehicle(v);

        i++;
    }
}
} // end class

这是错误日志:

03-27 18:30:47.274 4966-4966/clyky.cartracker E/AndroidRuntime: FATAL EXCEPTION: main
                                                            Process: clyky.cartracker, PID: 4966
                                                            java.lang.RuntimeException: Unable to start activity ComponentInfo{clyky.cartracker/clyky.cartracker.activities.VehicleListActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
                                                                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2434)
                                                                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2504)
                                                                at android.app.ActivityThread.-wrap11(ActivityThread.java)
                                                                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1347)
                                                                at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                at android.os.Looper.loop(Looper.java:148)
                                                                at android.app.ActivityThread.main(ActivityThread.java:5458)
                                                                at java.lang.reflect.Method.invoke(Native Method)
                                                                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                                                             Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
                                                                at clyky.cartracker.activities.fragments.LoadingVehicleListFragment.onActivityCreated(LoadingVehicleListFragment.java:51)
                                                                at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:2193)
                                                                at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1323)
                                                                at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1523)
                                                                at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1585)
                                                                at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:2832)
                                                                at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
                                                                at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:603)
                                                                at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:181)
                                                                at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1237)
                                                                at android.app.Activity.performStart(Activity.java:6268)
                                                                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2397)
                                                                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2504) 
                                                                at android.app.ActivityThread.-wrap11(ActivityThread.java) 
                                                                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1347) 
                                                                at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                at android.os.Looper.loop(Looper.java:148) 
                                                                at android.app.ActivityThread.main(ActivityThread.java:5458) 
                                                                at java.lang.reflect.Method.invoke(Native Method) 
                                                                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

在出现这些异常之前,我还遇到过一些“失败的活页夹交易”,例如:

03-27 18:30:41.955 1452-1452/com.google.android.inputmethod.latin E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 100)

03-27 18:30:41.956 1452-1452/com.google.android.inputmethod.latin E/AndroidIME: aqx: java.lang.RuntimeException: android.os.DeadObjectException: Transaction failed on small parcel;远程进程可能已经死了 03-27 18:30:41.999 1452-1452/com.google.android.inputmethod.latin E/JavaBinder: !!! Binder 交易失败!!! (包裹大小 = 100) 03-27 18:30:42.000 1452-1452/com.google.android.inputmethod.latin E/AndroidIME: aqx: java.lang.RuntimeException: android.os.DeadObjectException: Transaction failed on small parcel;远程进程可能已经死了 03-27 18:30:42.001 1452-1452/com.google.android.inputmethod.latin E/JavaBinder: !!! Binder 交易失败!!! (包裹大小 = 100) 03-27 18:30:42.002 1452-1452/com.google.android.inputmethod.latin E/AndroidIME: aqx: java.lang.RuntimeException: android.os.DeadObjectException: Transaction failed on small parcel;远程进程可能已经死了 03-27 18:30:42.005 1452-1452/com.google.android.inputmethod.latin E/JavaBinder: !!! Binder 交易失败!!! (包裹大小 = 100) 03-27 18:30:42.007 1452-1452/com.google.android.inputmethod.latin E/AndroidIME: aqx: java.lang.RuntimeException: android.os.DeadObjectException: Transaction failed on small parcel;远程进程可能已经死了 03-27 18:30:42.008 1452-1452/com.google.android.inputmethod.latin E/JavaBinder: !!! Binder 交易失败!!! (包裹大小 = 100) 03-27 18:30:42.010 1452-1452/com.google.android.inputmethod.latin E/AndroidIME: aqx: java.lang.RuntimeException: android.os.DeadObjectException: Transaction failed on small parcel;远程进程可能已经死了 03-27 18:30:42.026 1452-5094/com.google.android.inputmethod.latin E/JavaBinder: !!! Binder 交易失败!!! (包裹大小 = 168) 03-27 18:30:42.031 1452-5095/com.google.android.inputmethod.latin E/JavaBinder: !!! Binder 交易失败!!! (包裹大小 = 168) 03-27 18:30:43.509 1452-1452/com.google.android.inputmethod.latin E/JavaBinder: !!! Binder 交易失败!!! (包裹大小 = 100) 03-27 18:30:43.510 1452-1452/com.google.android.inputmethod.latin E/AndroidIME: aqx: java.lang.RuntimeException: android.os.DeadObjectException: Transaction failed on small parcel;远程进程可能已经死了 03-27 18:30:43.510 1452-1452/com.google.android.inputmethod.latin E/JavaBinder: !!! Binder 交易失败!!! (包裹大小 = 100) 03-27 18:30:43.512 1452-1452/com.google.android.inputmethod.latin E/AndroidIME: aqx: java.lang.RuntimeException: android.os.DeadObjectException: Transaction failed on small parcel;远程进程可能已经死了 03-27 18:30:43.542 1452-5121/com.google.android.inputmethod.latin E/JavaBinder: !!! Binder 交易失败!!! (包裹大小 = 168) 03-27 18:30:43.547 1452-5120/com.google.android.inputmethod.latin E/JavaBinder: !!! Binder 交易失败!!! (包裹大小 = 168)

但是,它们开始出现在抛出异常的操作之前,所以我认为这些错误没有影响。

【问题讨论】:

  • 你为什么在onCreateview中调用super.onAttach?您也可以在onCraateView 中使用getArguments(),缺点是onCreateView 执行速度较慢
  • @Bhargav 对onAttach 感到抱歉,这是一个复制粘贴错误,因为我首先尝试在片段的onAttach 中执行getArguments
  • 等待视图是否为片段膨胀?
  • 您确定 getArguments() 返回 null,请发布日志跟踪。如果在活动的onCreate中没有启动片段事务,如何调用onCreateView()
  • @Jagroshan 是的,我很确定。我已经发布了日志跟踪,并且我已经注意到之前有一个观察者

标签: android android-fragments android-activity


【解决方案1】:

onActivityCreated() 在创建宿主活动时在onCreateView() 方法之后调用。已创建活动和片段实例以及活动的视图层次结构。此时,可以使用findViewById() 方法访问视图。例子。在此方法中,您可以实例化需要 Context 对象的对象。

尝试在那里访问它,也不要在片段中存储上下文总是调用getActivity()

那个空指针是android框架中的执行流程造成的,onCreateView()fragment第一次绘制用户界面的时候系统调用这个回调。要为您的 Fragment 绘制 UI,您必须从此方法返回一个 View 组件,该组件是您的 Fragment 布局的根。如果片段不提供 UI,您可以返回 null。 因此它首先被调用,因此给出了空指针异常。

【讨论】:

  • 尝试在该方法中获取参数。
  • 感谢您的回答。正如你所说,我试图在onActivityCreated 中获得论据,但它仍然无法正常工作。现在活动的onCreated 被调用得很好,但onActivityCreated 从未被调用(我放在那里的断点从未被调用)
  • 这是有线的,我建议只使用共享首选项文件来共享感兴趣的内容。
【解决方案2】:

你可以试试这个吗?

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_vehicle_list);
    vehicles = new ArrayList<>();

    String userID;
    Bunlde bundle = getIntent().getExtras();
    if(bundle != null){
        userID = bundle.getString("userID");
    }

    if(savedInstanceState == null){
          LoadingVehicleListFragment f = new LoadingVehicleListFragment();
          Bundle fArguments = new Bundle();
          fArguments.putString("userID", userID);
          f.setArguments(fArguments);
          getSupportFragmentManager().beginTransaction().replace(R.id.loadingVehicleFragment, f).commit();
    }
}

【讨论】:

  • 谢谢,我试过了,但onActivityCreated 中的getArguments 仍然返回null
  • 你能发送整个片段代码吗?出了点问题。
  • 我编辑了我的代码。我认为您在开始活动时没有输入 userId。
  • 谢谢,但是是的,我已将“userID”作为要传递的参数。直接是getArguments返回null,并不是说“userID”不存在。
猜你喜欢
  • 2012-12-28
  • 2016-12-18
  • 1970-01-01
  • 2013-06-16
  • 2012-12-15
  • 1970-01-01
  • 2015-07-29
  • 1970-01-01
  • 2014-09-17
相关资源
最近更新 更多