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