Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android fragment implementation issue

Here's my xml for my fragment:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context="com.thenewjonathan.foodtracker.fragments.FoodItemDisplay"
    >
<TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="50dp"
        android:textStyle="bold"
        android:text="blank"
        android:id="@+id/foodItemNameView"
        android:gravity="center"
        android:layout_gravity="top|left|center"
        android:textAlignment="center"/>
<ImageView
        android:contentDescription="@string/foodPicture"
        android:layout_width="241dp"
        android:layout_height="241dp"
        android:layout_gravity="left|center_vertical"
        android:background="@color/material_blue_grey_800"
        android:layout_below="@id/foodItemNameView"
        android:id="@+id/foodPic"
        />
<RelativeLayout
        android:layout_width="140dp"
        android:layout_height="241dp"
        android:layout_alignParentRight="true"
        android:layout_below="@id/foodItemNameView"
        android:layout_gravity="end|center_vertical"
        android:gravity="center"
        android:id="@+id/checkBoxGroup"
        >
    <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Monday"
            android:id="@+id/mondayBox"
            android:layout_alignParentTop="true"
            android:layout_alignParentStart="true"/>
    <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Tuesday"
            android:id="@+id/tuesdayBox"
            android:layout_below="@id/mondayBox"
            android:layout_alignParentStart="true"/>
    <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Wednesday"
            android:id="@+id/wednesdayBox"
            android:layout_below="@id/tuesdayBox"
            android:layout_alignParentStart="true"/>
    <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Thursday"
            android:id="@+id/thursdayBox"
            android:layout_below="@id/wednesdayBox"
            android:layout_alignParentStart="true"/>
    <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Friday"
            android:id="@+id/fridayBox"
            android:layout_below="@id/thursdayBox"
            android:layout_alignParentStart="true"/>
    <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Saturday"
            android:id="@+id/saturdayBox"
            android:layout_below="@id/fridayBox"
            android:layout_alignParentStart="true"/>
    <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Sunday"
            android:id="@+id/sundayBox"
            android:layout_below="@id/saturdayBox"
            android:layout_alignParentStart="true"/>
</RelativeLayout>

Here is my java file for the fragment: (FoodItem is just a custom object I'm using to store the info about each food item that the fragment represents)

package com.thenewjonathan.foodtracker.fragments;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import com.thenewjonathan.foodtracker.R;
import com.thenewjonathan.foodtracker.enums.GoodBad;
import com.thenewjonathan.foodtracker.objects.FoodItem;

public class FoodItemDisplay extends Fragment
{
    private static final String FOOD_ITEM_NAME = "blank";

    private FoodItem foodItem;
    private String foodItemName;

    private ImageView image;
    private TextView itemNameView;
    private CheckBox mondayBox;
    private CheckBox tuesdayBox;
    private CheckBox wednesdayBox;
    private CheckBox thursdayBox;
    private CheckBox fridayBox;
    private CheckBox saturdayBox;
    private CheckBox sundayBox;

    public FoodItemDisplay()
    {
        setFoodItem(new FoodItem("blank", GoodBad.HEALTHY, "blank"));
    }



public static FoodItemDisplay newInstance(String inFoodItemName)
    {
        FoodItemDisplay fragment = new FoodItemDisplay();
        Bundle args = new Bundle();
        args.putString(FOOD_ITEM_NAME, inFoodItemName);
        fragment.setArguments(args);
        return fragment;
    }



@Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        if (getArguments() != null)
        {
            foodItemName = getArguments().getString(FOOD_ITEM_NAME);
        }
        itemNameView = (TextView) itemNameView.findViewById(R.id.foodItemNameView);
        image = (ImageView) image.findViewById(R.id.foodPic);
        mondayBox = (CheckBox) mondayBox.findViewById(R.id.mondayBox);
        tuesdayBox = (CheckBox) tuesdayBox.findViewById(R.id.tuesdayBox);
        wednesdayBox = (CheckBox) wednesdayBox.findViewById(R.id.wednesdayBox);
        thursdayBox = (CheckBox) thursdayBox.findViewById(R.id.thursdayBox);
        fridayBox = (CheckBox) fridayBox.findViewById(R.id.fridayBox);
        saturdayBox = (CheckBox) saturdayBox.findViewById(R.id.saturdayBox);
        sundayBox = (CheckBox) sundayBox.findViewById(R.id.sundayBox);

        if (foodItem != null)
        {
            setValues();
        }
    }

    public void setValues()
    {
        if(itemNameView == null)
        {
            return;
        }
        itemNameView.setText(foodItem.getName());
        image.setImageResource(image.getResources()
                .getIdentifier(foodItem.getImgName(), "drawable", this.getClass().getPackage().toString()));
        mondayBox.setChecked(foodItem.isMonday());
        tuesdayBox.setChecked(foodItem.isTuesday());
        wednesdayBox.setChecked(foodItem.isWednesday());
        thursdayBox.setChecked(foodItem.isThursday());
        fridayBox.setChecked(foodItem.isFriday());
        saturdayBox.setChecked(foodItem.isSaturday());
        sundayBox.setChecked(foodItem.isSunday());
    }

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

    @Override
    public void onAttach(Activity activity)
    {
        super.onAttach(activity);
    }

    @Override
    public void onDetach()
    {
        super.onDetach();
    }

    public FoodItem getFoodItem()
    {
        return foodItem;
    }

    public void setFoodItem(FoodItem foodItem)
    {
        this.foodItem = foodItem;
    }

    public String getFoodItemName()
    {
        return foodItemName;
    }

    public void setFoodItemName(String foodItemName)
    {
        this.foodItemName = foodItemName;
    }
}

Here is the class I'm putting the fragments in place with:

public class HealthyFoods extends Activity
{
    private ArrayList<FoodItem> foodItemList;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.healthy_foods);

        foodItemList = new ArrayList<FoodItem>();
        foodItemList.add(new FoodItem("Turkey Burger", GoodBad.HEALTHY, "burger"));

        FragmentManager fm = getFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        for(FoodItem fi : foodItemList)
        {
            FoodItemDisplay fid = FoodItemDisplay.newInstance(fi.getName());
            fid.setFoodItem(fi);
            fid.setValues();
            ft.add(R.id.healthyTab, fid);
        }
        ft.commit();
    }
}

When I run it, I'm getting this stack trace:

java.lang.NullPointerException
    at com.android.ddmlib.JdwpPacket.writeAndConsume(JdwpPacket.java:213)
    at com.android.ddmlib.Client.sendAndConsume(Client.java:675)
    at com.android.ddmlib.HandleHello.sendHELO(HandleHello.java:195)
    at com.android.ddmlib.HandleHello.sendHelloCommands(HandleHello.java:66)
    at com.android.ddmlib.Client.getJdwpPacket(Client.java:772)
    at com.android.ddmlib.MonitorThread.processClientActivity(MonitorThread.java:317)
    at com.android.ddmlib.MonitorThread.run(MonitorThread.java:263)

I was doing ok on this project because I could see the stack trace into the code I wrote and finding errors. But when I hit this one, it's giving me stack traces for code I didn't write. I know that this indicates that I set something up wrong, but Google is not being very helpful on this one and I have been over this code several times and don't see anything wrong based on the documentation for each of the objects and classes I'm using... Has anyone ever ran into this before? Maybe have some ideas of what to look at? Or just straight up have an answer? lol. I'm using intellij-idea (not android studios).

Thanks! Jon

* FROM COMMENTS BELOW * Here's the adb log output:

DeviceMonitor: Adb rejected connection to client '27925': closed
DeviceMonitor: Adb rejected connection to client '27952': closed
DeviceMonitor: Adb rejected connection to client '28560': closed
DeviceMonitor: Adb rejected connection to client '31166': closed
DeviceMonitor: Adb rejected connection to client '31790': closed
DeviceMonitor: Adb rejected connection to client '32138': closed
DeviceMonitor: Adb rejected connection to client '578': closed
DeviceMonitor: Adb rejected connection to client '578': closed
ddms: null
java.lang.NullPointerException
    at com.android.ddmlib.JdwpPacket.writeAndConsume(JdwpPacket.java:213)
    at com.android.ddmlib.Client.sendAndConsume(Client.java:675)
    at com.android.ddmlib.HandleHello.sendHELO(HandleHello.java:195)
    at com.android.ddmlib.HandleHello.sendHelloCommands(HandleHello.java:66)
    at com.android.ddmlib.Client.getJdwpPacket(Client.java:772)
    at com.android.ddmlib.MonitorThread.processClientActivity(MonitorThread.java:317)
    at com.android.ddmlib.MonitorThread.run(MonitorThread.java:263)

ddms: null
java.lang.NullPointerException
    at com.android.ddmlib.JdwpPacket.writeAndConsume(JdwpPacket.java:213)
    at com.android.ddmlib.Client.sendAndConsume(Client.java:675)
    at com.android.ddmlib.HandleHello.sendHELO(HandleHello.java:195)
    at com.android.ddmlib.HandleHello.sendHelloCommands(HandleHello.java:66)
    at com.android.ddmlib.Client.getJdwpPacket(Client.java:772)
    at com.android.ddmlib.MonitorThread.processClientActivity(MonitorThread.java:317)
    at com.android.ddmlib.MonitorThread.run(MonitorThread.java:263)

DeviceMonitor: Adb rejected connection to client '832': closed
DeviceMonitor: Adb rejected connection to client '3083': closed
DeviceMonitor: Adb rejected connection to client '5816': closed
DeviceMonitor: Adb rejected connection to client '5847': closed
DeviceMonitor: Adb rejected connection to client '6144': closed
PropertyFetcher: AdbCommandRejectedException getting properties for device LGUS990611b931f: device offline
PropertyFetcher: AdbCommandRejectedException getting properties for device LGUS990611b931f: device unauthorized. Please check the confirmation dialog on your device.
PropertyFetcher: AdbCommandRejectedException getting properties for device LGUS990611b931f: device unauthorized. Please check the confirmation dialog on your device.
PropertyFetcher: AdbCommandRejectedException getting properties for device LGUS990611b931f: device unauthorized. Please check the confirmation dialog on your device.

New error now after some reconfiguring: Ok... new error now ->

Caused by: java.lang.IllegalArgumentException: No view found for id 0x7f09005a (com.thenewjonathan.foodtracker:id/healthyTab) for fragment FoodItemDisplay{b5abff #0 id=0x7f09005a}
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:886)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
            at android.app.BackStackRecord.run(BackStackRecord.java:833)
            at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1452)
            at android.app.Activity.performStart(Activity.java:6035)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2269)
            at android.app.ActivityThread.startActivityNow(ActivityThread.java:2128)
            at android.app.LocalActivityManager.moveToState(LocalActivityManager.java:135)
            at android.app.LocalActivityManager.startActivity(LocalActivityManager.java:347)
            at android.widget.TabHost$IntentContentStrategy.getContentView(TabHost.java:756)
            at android.widget.TabHost.setCurrentTab(TabHost.java:420)
            at android.widget.TabHost.addTab(TabHost.java:247)
            at com.thenewjonathan.foodtracker.MainMenu.onCreate(MainMenu.java:30)
            at android.app.Activity.performCreate(Activity.java:6020)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2259)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2368)
            at android.app.ActivityThread.access$800(ActivityThread.java:149)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5299)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)

And it's happening in the oncreate of my main menu that is adding the tabs on when I try to add the "healthy" tab to the tabhost:

public class MainMenu extends ActivityGroup
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.main_menu);

        TabHost container = (TabHost) findViewById(R.id.mainTabHost);
        container.setup(this.getLocalActivityManager());
        TabSpec healthy = container.newTabSpec("Healthy Foods").setContent(new Intent(this, HealthyFoods.class))
                .setIndicator("Healthy Foods");
        TabSpec unHealthy = container.newTabSpec("Unhealthy Foods").setContent(new Intent(this, UnHealthyFoods.class))
                .setIndicator("Unhealthy Foods");

        container.addTab(healthy);
        container.addTab(unHealthy);
    }
}
like image 927
Jon Sansoucie Avatar asked Jul 02 '15 17:07

Jon Sansoucie


People also ask

Are fragments still used in Android?

Here are the important things to understand about fragments: A Fragment is a combination of an XML layout file and a java class much like an Activity . Using the support library, fragments are supported back to all relevant Android versions.

Why onActivityCreated is deprecated?

Need for onActivityCreated() deprecation In such similar fashion android developers saw the tight coupling of code dependent to the Activity's life cycle. And they decided that it is not a good practice anymore to be dependent on the activity attach to do certain things inside the fragment.

Are fragments deprecated Android?

Register and create a developer profile to keep track of sessions you're interested in by saving them to My I/O.


2 Answers

You are referencing your views wrong inside of onCreate() in the fragment class. You should obtain their references inside onCreateView() doing something like this:

View view = inflater.inflate(R.layout.food_item_display, container, false);
itemNameView = (TextView) view.findViewById(R.id.foodItemNameView);
image = (ImageView) view.findViewById(R.id.foodPic);

The way you have it written, you are trying to reference the views before you've given them a value, hence the NPE. If food_item_display is in fact the parent layout for all these items, you should be using that View to find the others by ID, as I've shown here.

like image 151
AdamMc331 Avatar answered Sep 28 '22 10:09

AdamMc331


You must use onActivityCreated or onCreateView to get references such as the following example. You can't use onCreate for doing so, because the fragment will only be created after onCreateView.

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

@Override
public void onActivityCreated(Bundle savedInstanceState){

    View _view = getView();

    itemNameView = (TextView) _view.findViewById(R.id.foodItemNameView);
    image = (ImageView) _view.findViewById(R.id.foodPic);
    mondayBox = (CheckBox) _view.findViewById(R.id.mondayBox);
    tuesdayBox = (CheckBox) _view.findViewById(R.id.tuesdayBox);
    wednesdayBox = (CheckBox) _view.findViewById(R.id.wednesdayBox);
    thursdayBox = (CheckBox) _view.findViewById(R.id.thursdayBox);
    fridayBox = (CheckBox) _view.findViewById(R.id.fridayBox);
    saturdayBox = (CheckBox) _view.findViewById(R.id.saturdayBox);
    sundayBox = (CheckBox) _view.findViewById(R.id.sundayBox);

}

Another example:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    View _view = inflater.inflate(R.layout.food_item_display, container, false);

    itemNameView = (TextView) _view.findViewById(R.id.foodItemNameView);
    image = (ImageView) _view.findViewById(R.id.foodPic);
    mondayBox = (CheckBox) _view.findViewById(R.id.mondayBox);
    tuesdayBox = (CheckBox) _view.findViewById(R.id.tuesdayBox);
    wednesdayBox = (CheckBox) _view.findViewById(R.id.wednesdayBox);
    thursdayBox = (CheckBox) _view.findViewById(R.id.thursdayBox);
    fridayBox = (CheckBox) _view.findViewById(R.id.fridayBox);
    saturdayBox = (CheckBox) _view.findViewById(R.id.saturdayBox);
    sundayBox = (CheckBox) _view.findViewById(R.id.sundayBox);

    return _view;
}
like image 42
Lennon Spirlandelli Avatar answered Sep 28 '22 11:09

Lennon Spirlandelli