简体   繁体   中英

Android Java: Fragments returning null view in onCreateView()

I am currently working on a program that uses an MVC design pattern and fragments in android java. I have figured out one of my fragments and gotten it working but when I copied the other fragments to follow the same code structure (with specialized functionality), I get a null pointer exception in the onCreateView method.

I'm on my junk laptop right now and it can't seem to handle android emulation so I can post the exact error code tomorrow. I have my source code though and I have been hitting my head against the wall long enough to know where it is breaking.

EDIT: I see my problem. I'm testing the my code by calling a method from within the View.java class from each fragment. This method updates a table in the view. Since the views haven't been displayed on screen yet, onCreateView() hasn't been called for them. Since onCreateView() hasn't been called, trying to access the view results in a null pointer. Is there any good way to call onCreateView() for each fragment from my MainActivity just so I can initialize the views early?

(Part of the working fragment):

    public class DispatchView extends Fragment {
private final List<DispatchModel> models = new ArrayList<DispatchModel>();

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.dispatchfragment, container,
            false);
    return view;
}

All fragments, except for DispatchView, break upon returning view. They are returning null rather than an actual object. Part of one of the broken fragments:

    public class ConnectionsLogView extends Fragment {
private final List<ConnectionsLogModel> models = new ArrayList<ConnectionsLogModel>();

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.connectionslogfragment,
            container, false);
    return view;
}

The fragments are declared and initialized. They (any of them except the Dispatch MVC) break after I try to push a new data entry (class) into them. In my MainActivity.java:

    public class MainActivity extends Activity {
// Declare Tab Variables and fragment objects
private mDMI             app;
ActionBar.Tab            Tab1, Tab2, Tab3, Tab4;
Fragment                 dispatchTab          = new DispatchView();
Fragment                 dispatchLogTab       = new DispatchLogView();
Fragment                 activeConnectionsTab = new ConnectionsView();
Fragment                 connectionLogTab     = new ConnectionsLogView();
DispatchModel            dispatchModel;
DispatchController       dispatchController;
DispatchLogModel         dispatchLogModel;
DispatchLogController    dispatchLogController;
ConnectionsModel         connectionsModel;
ConnectionsController    connectionsController;
ConnectionsLogModel      connectionsLogModel;
ConnectionsLogController connectionsLogController;

public MainActivity() {
    super();
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    app = (mDMI) getApplication();
    dispatchModel = app.getDispatchModel();
    dispatchController = new DispatchController(dispatchTab, dispatchModel);
    dispatchLogModel = app.getDispatchLogModel();
    dispatchLogController = new DispatchLogController(dispatchLogTab,
            dispatchLogModel);
    connectionsModel = app.getConnectionsModel();
    connectionsController = new ConnectionsController(activeConnectionsTab,
            connectionsModel);
    connectionsLogModel = app.getConnLogModel();
    connectionsLogController = new ConnectionsLogController(
            connectionLogTab, connectionsLogModel);
    setContentView(R.layout.activity_main);

The xml strings are identified In my R.java:

    public static final class layout {
    public static final int activity_login=0x7f030000;
    public static final int activity_main=0x7f030001;
    public static final int connectionsfragment=0x7f030002;
    public static final int connectionslogfragment=0x7f030003;
    public static final int dispatchfragment=0x7f030004;
    public static final int dispatchlogfragment=0x7f030005;
}

Don't create your fragments that way. Instead use a standard Android pattern:

public class FeedFragment extends Fragment {
   public FeedFragment() {
     super();
   }
   public static FeedFragment newInstance(Context context) {
     if (context != null) {
       sContext = context.getApplicationContext();
     } else {
       sContext = YourApp.getInstance().getApplicationContext();
     }
     return new FeedFragment();
   }
 }

Then don't create them like that in your activity…

instead use a standard Android pattern in your Activity:

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.content_frame);
        if ( fragment == null ) {
            fragment = FeedFragment.newInstance(this);
            fm.beginTransaction()
                    .add(R.id.content_frame, dispatchTab, "DISPATCH_FRAG")
                    .commit();
        }
    }

To retrieve the fragment later you can do…

final FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentByTag("DISPATCH_FRAG);
if (fragment != null) {
   // cast and use your fragment
}

You can even store a reference if you need it later.

Regarding your null problem, it's really hard to tell without the exact crash/log.

But your code is a little bit messy and that may be the cause. Fragment LifeCycle is tricky.

I fixed it myself. If the view returns null, my update functions dont try to add rows and entries to the (nonexisting) table in the (nonexisting) view. I implemented this in each view like so:

public void update(final BlockingDeque<Dispatch> dispatches) {
    View view = getView();
    // do not update if the view is null (device is not displaying that
    // fragment)
    if (view != null) {
        TableLayout t = (TableLayout) view.findViewById(R.id.dispatchTable);
        t.removeAllViews();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM