-2

Good day all,

I have an issue where my activity is making a network call and when the network call is completed, it makes some changes in the activity using the data from the JSON object received from the call, it then passes the object down to the fragments in the same activity. These fragments are in a TabLayout.

I had this same issue which I asked here at this SO Question That sorted it out but I seem to be having the same issue, even after it worked for a little bit after not changing anything significant. I was just adding more fields I wanted to change?

The issue I have is that if I put a System.out.println() it prints out the correct data. The minute I want to set say a TextView with the data I receive in the Fragment the app Crashes with Nullpointer. When I debug it with the Debug in Android studio, the TextView I'm setting is always null for some reason.

Activity Code that does the initial Network call:

  @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listings);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
handleIntent(getIntent());

}


private void handleIntent(Intent aIntent) {
if (aIntent != null) {

  String tradeType = aIntent.getStringExtra("itemType");
  String tradeId = aIntent.getStringExtra("itemId");

  presenter = new ItemPresenterImpl(this, ItemBuyNowActivity.this);   
  presenter.doListingServiceCall(tradeId); // <------- This is the where I send the Trade Id so I can do the network call.
} else {
  System.out.println("Intent is null in " + ItemBuyNowActivity.class.getSimpleName());
}

}

Interface between Activity and Presenter:

public interface ItemPresenter {

void doListingServiceCall(String itemId);  //<------- Comes to this Interface

void doToolbarBackgroundImageCall(TradeItem aTradeItem);

}

Class the implements the Presenter:

@Override
  public void doListingServiceCall(String aItemId) {  // <------- This is where the network call starts
    String homeURL = BobeApplication.getInstance().getWsURL() + mContext.getString(R.string.ws_url_item) + aItemId;
    BobeJSONRequest jsObjRequest = new BobeJSONRequest(Request.Method.GET, homeURL, null, this, this);
    VolleySingleton.getInstance().addToRequestQueue(jsObjRequest, "ListingRequest");
  }

  @Override
  public void doToolbarBackgroundImageCall(TradeItem aTradeItem) {
    ImageRequest request = new ImageRequest(aTradeItem.getItem().getImageUrl(),
            new Response.Listener<Bitmap>() {
              @Override
              public void onResponse(Bitmap bitmap) {
                Drawable drawable = new BitmapDrawable(mContext.getResources(), bitmap);
                mItemView.loadBackgroundImage(drawable);
              }
            }, 0, 0, null,
            new Response.ErrorListener() {
              public void onErrorResponse(VolleyError error) {
                mItemView.displayErrorMessage(VolleyErrorHelper.getErrorType(error, mContext) + " occurred downloading background image");
              }
            });
    VolleySingleton.getInstance().addToRequestQueue(request, "ListItemToolbarBackgroundImageRequest");
  }

  @Override
  public void onResponse(Object response) { 
    Gson gson = new Gson();
    TradeItem tradeItem = gson.fromJson(response.toString(), TradeItem.class);
    mItemView.populateListViews(tradeItem); // <------- This is the where I send the Object so the views in the activity can be manipulated
    doToolbarBackgroundImageCall(tradeItem);
  }

Method in the Activity that handles

  @Override
public void populateListViews(TradeItem aTradeItem) {
  mOverviewPresenter = new OverviewPresenterImpl(new OverviewListItemFragment(), aTradeItem);
  OverviewListItemFragment.setData(aTradeItem);  //<------- This is the where I send the Object to the fragment so i can manipulate the views in the fragment
}
class TabAdapter extends FragmentPagerAdapter {
    public TabAdapter(FragmentManager fm) {
      super(fm);
    }

    @Override
    public Fragment getItem(int position) {
      Fragment fragment = null;

      if (position == 0) {
        fragment = new OverviewListItemFragment();
      }
      if (position == 1) {
        fragment = new DescriptionListItemFragment();
      }
      if (position == 2) {
        fragment = new ShippingListItemFragment();
      }
      if (position == 3) {
        fragment = new PaymentListItemFragment();
      }
      return fragment;
    }

    @Override
    public int getCount() {
      return 4;
    }

    @Override
    public CharSequence getPageTitle(int position) {
      if (position == 0) {
        return "Overview";
      }
      if (position == 1) {
        return "Description";
      }
      if (position == 2) {
        return "Shipping";
      }
      if (position == 3) {
        return "Payment";
      }
      return null;
    }
  }

The Fragment that receives the data:

    public class OverviewListItemFragment extends Fragment implements OverviewView {

  private static TextView mOverViewHeading;

  public OverviewListItemFragment() {
  }

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  }

  @Nullable
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.overview_list_item_fragment, container, false);
    mOverViewHeading = (TextView) view.findViewById(R.id.frag_overview_heading_textview);
    return view;

  }

  @Override
  public void populateOverviewViews(final TradeItem aTradeItem) {
    System.out.println("Overview Trade Object title is:" + aTradeItem.getItem().getTradeTitle());  // <------- This is print statement works 100% but when I try setting mOverViewHeading to the text in aTradeItem.getItem().getTradeTitle() I get a Null pointer Exception.

  }

  public static void setData(TradeItem aTradeItem) {
    System.out.println("Overview Trade Object title is:" + aTradeItem.getItem().getTradeTitle());  // <------- This is print statement works 100% but when I try setting mOverViewHeading to the text in aTradeItem.getItem().getTradeTitle() I get a Null pointer Exception.
    mOverViewHeading.setText(aTradeItem.getItem().getTradeTitle());// <------- This is where it crashes and mOverViewHeading is still null at this point.
  }
}

EDIT: Sorry I forgot the LogCat:

02-05 17:08:21.554 30512-30512/com.example.app E/AndroidRuntime: FATAL EXCEPTION: main
                                                          java.lang.NullPointerException
                                                              at com.example.app.ui.fragments.OverviewListItemFragment.setData(OverviewListItemFragment.java:46)
                                                              at com.example.app.ui.activities.ItemBuyNowActivity.populateListViews(ItemBuyNowActivity.java:95)
                                                              at com.example.app.listing.ItemPresenterImpl.onResponse(ItemPresenterImpl.java:62)
                                                              at com.android.volley.toolbox.JsonRequest.deliverResponse(JsonRequest.java:65)
                                                              at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
                                                              at android.os.Handler.handleCallback(Handler.java:725)
                                                              at android.os.Handler.dispatchMessage(Handler.java:92)
                                                              at android.os.Looper.loop(Looper.java:137)
                                                              at android.app.ActivityThread.main(ActivityThread.java:5041)
                                                              at java.lang.reflect.Method.invokeNative(Native Method)
                                                              at java.lang.reflect.Method.invoke(Method.java:511)
                                                              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
                                                              at dalvik.system.NativeStart.main(Native Method)

My thinking is that the view I'm trying to set isn't "Active" (if thats the right word) at the time it receives the data, because when I run the debugger with a break point at the method that receives the data in the Fragment, the mOverViewHeading TextView id is null, even though I have the findViewById in the onCreate, also tried placing it in the onCreateView() but both times failed. I also tried placing the findViewById in the same method that gets called when the response is successful but before I try setting the setText() on the TextView.

Thank you

Community
  • 1
  • 1
Stillie
  • 2,647
  • 6
  • 28
  • 50
  • Its crashing in `DescriptionListItemFragment`, method `populateDescriptionViews`, line# 37. Where is the code? – Rohit5k2 Feb 08 '16 at 11:51
  • Sorry, Please see the alterations to the logcat, i have the same issue on all the Tabs of my Tablayout. – Stillie Feb 08 '16 at 11:54
  • Possible duplicate of [What is a Null Pointer Exception, and how do I fix it?](http://stackoverflow.com/questions/218384/what-is-a-null-pointer-exception-and-how-do-i-fix-it) – Selvin Feb 08 '16 at 12:01
  • Looks like you haven't initialized `mItemView`. Please check. – Rohit5k2 Feb 08 '16 at 12:01
  • @Selvin thanks for that, was a good read but it didnt help me solve my solution, due to the fact the mOverViewHeading is still null by the time it is asked to have its Text changed, even though i have called view.findViewById in the onCreateView – Stillie Feb 08 '16 at 12:20
  • @Rohit5k2 it is initialized, its just not in this code – Stillie Feb 08 '16 at 12:20

1 Answers1

1

OverviewListItemFragment I assume this is not your added fragment instance, but the class.

I suggest the following changes: remove static from setData and your TextView, leave it, if you really know how it works. I don't think it is necessary or recommendable.

private OverviewListItemFragment mFrag; //declare globally

mFrag = new OverviewListItemFragment(); 
//if you do not want to add it now, ignore the following line
getSupportFragmentManager().beginTransaction().add(R.id.yourContainer, mFrag, "mFrag").commit();

now call mFrag.setData everytime you want to set your data. Check if your mFrag is null, then reinitialize, and maybe re-add, or whatever you want to do.

Edit: Now that I know that you use a ViewPager, I suggest the following:

Do the above. I don't think it is recommendable to have static methods in this Context. You get an error because you are trying to reach a TextView in your Fragment. This was initialized in a ViewPager/PagerAdapter, and the PagerAdapter holds the reference to the used instance of your fragment. You can access your used fragment through

 Fragment mFragment = pagerAdapter.getFragment(0); //frag at position 0

with some casting, you will be able to find your (now NOT static) method:

((OverviewListItemFragment)pagerAdapter.getFragment(0)).setData(YOUR_DATA);

Please add some try/catch. check if your fragment is null, because it is possible that your fragment is recycled in the FragmentPagerAdapter, because it reached the offset. Another way to achieve this, would be to store your required data, and update it everytime your fragment gets visible as described here.

Edit 2: Obviously, You'll need some changed in your Adapter:

I would recommend creating an array containing your fragment in the constructor:

//global in your adapter:
private Fragment[] fragments;

public CustomPagerAdapter(FragmentManager fm) {
        super(fm);
        fragments = new GameFragment[4];
        fragments[0] = new MyFragment();
        fragments[1] = new SecondFragment();
        ....
    }
    public Fragment getItem(int position) {
       return fragments[position];
    }

    public Fragment getFragment(int position) {
       return fragments[position];
    }
Community
  • 1
  • 1
yennsarah
  • 5,467
  • 2
  • 27
  • 48
  • thanks but I may be wrongn in saying this but I think the issue is with the view rather than the fragment? MOverview text heading and any other view i.e. Other text views are bull by the time the data is return whether it's by using the interfaces or a public method? – Stillie Feb 08 '16 at 19:31
  • How do you add your Fragment..? – yennsarah Feb 08 '16 at 19:41
  • Please look at the alterations. I added more code to the Activity that holds the fragments – Stillie Feb 09 '16 at 07:16
  • Ok. Now I got your problem. It was necessary to know that you use a ViewPager. I'll edit my answer. – yennsarah Feb 09 '16 at 07:35
  • Thanks for this, Im having trouble calling getFragment on pagerAdapter? any ideas why? – Stillie Feb 09 '16 at 09:05
  • Because I forgot something essential... Give me a second. ^^' – yennsarah Feb 09 '16 at 09:09
  • If you feel that my answer helped you, you could [accept my answer](http://meta.stackexchange.com/a/5235) – yennsarah Feb 11 '16 at 10:08