Android fragment implementation issue
Asked Answered
S

2

8

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);
    }
}
Scrimp answered 2/7, 2015 at 17:27 Comment(5)
I think you're missing a few lines in that logcat, please add the full error.Derrik
^ Eventually the logcat will give you the line from your code that caused the error, even if it happened somewhere in a library that you imported (which this looks like).Hoarhound
Look at the way you're getting a reference to the views. itemNameView = (TextView) itemNameView... will throw an NPE, because itemNameView was never instantiated.Hoarhound
Will have to attach a file I fear to give you the whole text of my adb logScrimp
If it's too long to post in the question, use Gist or PasteBin and share the link.Hoarhound
H
4

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.

Hoarhound answered 2/7, 2015 at 17:43 Comment(1)
You are 100% right.. thanks for that. Was just plugging and chugging and letting the idea do the work... not sure why is used my objects to find the view... weird. However, it didn't fix the problem.. still having the issue. I'll put the full text of my adb log in the comment above where the other guy asked for it.Scrimp
M
2

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;
}
Merrimerriam answered 2/7, 2015 at 18:2 Comment(7)
Are there major differences between doing this in onCreateView() or onActivityCreated()?Hoarhound
A little bit. Take a look #28930137Merrimerriam
Got the same error -> 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)Scrimp
Try to extend your activity from FragmentActivity instead of a simple ActivityMerrimerriam
In that case, you will use FragmentManager fm = getSupportFragmentManager(); instead of FragmentManager fm = getFragmentManager();Merrimerriam
It didn't find R.id.healthyTab at ft.add(R.id.healthyTab, fid); line in the HealthyFoods class.Merrimerriam
I was analyzing your code and if I'm right, you're trying to use HealthyFoods into a Tab, aren't you? Then you have the MainMenu as main activity, so in my view HealthyFoods would be a fragment instead. You should set a fragment into Tab and not activityMerrimerriam

© 2022 - 2024 — McMap. All rights reserved.