0

I got really anoying problem with accessing methods in Fragment.

Error that I got

Process: com.crelix.crelix, PID: 18913 java.lang.NullPointerException: Attempt to invoke virtual method 'void com.crelix.crelix.ClickerFragment.refreshViews()' on a null object reference at com.crelix.crelix.NavigationActivity.Refresh(NavigationActivity.java:530) at com.crelix.crelix.NavigationActivity$1$1.run(NavigationActivity.java:84) at android.os.Handler.handleCallback(Handler.java:810) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:189) at android.app.ActivityThread.main(ActivityThread.java:5529) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:950) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:745)

My Fragment Example:

    package com.crelix.crelix;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.CardView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;

import org.w3c.dom.Text;

public class ClickerFragment extends Fragment {

        public static ClickerFragment newInstance() {
            ClickerFragment fragment = new ClickerFragment();
        return fragment;
    }

    public ClickerFragment() {
    }

private TextView MoneyText;
private TextView MoneyPerTapTView;
private TextView BoxesText;
private TextView BoxesPerTapTView;
private ProgressBar progressBar;

MainHolder Main = new MainHolder();

public void refreshViews(){
    MoneyText.setText("Money: " +Main.Money[0]);
    MoneyPerTapTView.setText("$ " + Main.Money[1] + " per tap");
    BoxesText.setText("Boxes: " + Main.Boxes[0] + "/100");
    BoxesPerTapTView.setText("Points " + Main.Boxes[1] + " per tap");
    progressBar.setProgress(Main.Boxes[0]);
}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_clicker, container, false);
        MoneyText = (TextView) rootView.findViewById(R.id.MoneyText);
        MoneyPerTapTView = (TextView) rootView.findViewById(R.id.MoneyPerTapTView);
        BoxesText = (TextView) rootView.findViewById(R.id.BoxesText);
        BoxesPerTapTView = (TextView) rootView.findViewById(R.id.BoxesPerTapTView);
        progressBar = (ProgressBar) rootView.findViewById(R.id.progressBar);
        return rootView;
    }

}

And I want to access it from MainActivity like:

 public void Refresh()
{
    ClickerFragment ClickerFragment = (ClickerFragment) getSupportFragmentManager().findFragmentById(R.id.ClickerFragment);
    ClickerFragment.refreshViews();
}

Here I add my Fragments

 public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();

    Fragment fragment = null;
    if (id == R.id.nav_clicker) {
        fragment = new ClickerFragment();
    } else if (id == R.id.nav_upgrades) {
        fragment = new UpgradeFragment();
    } else if (id == R.id.nav_warehouse) {
        fragment = new WarehouseFragment();
    } else if (id == R.id.nav_postservice) {
        fragment = new PostserviceFragment();
    } else if (id == R.id.nav_shop) {
        fragment = new ShopFragment();
    } else if (id == R.id.nav_market) {
        fragment = new MarketFragment();
    } else if (id == R.id.nav_workshop) {
        fragment = new WorkshopFragment();
    } else if (id == R.id.nav_garage) {
        fragment = new GarageFragment();
    } else if (id == R.id.nav_museum) {
        fragment = new MuseumFragment();
    } else if (id == R.id.nav_collections) {
        fragment = new CollectionsFragment();
    }
    if (fragment != null) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.frame_container, fragment).commit();
    }
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}
jazzurro
  • 23,179
  • 35
  • 66
  • 76
trakasi
  • 27
  • 8
  • 1
    Possible duplicate of [What is a NullPointerException, and how do I fix it?](http://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – Nissa Dec 01 '16 at 14:35
  • The problem with this is it's not checking if the fragment is visible or the element have been created yet. Look at the lifecycle of a fragment for further clarification, but the gist of it is most likely onCreateView hasn't fired yet when you're trying to call refreshViews. – aminner Dec 01 '16 at 14:41
  • @Manza Edited. ;) – trakasi Dec 01 '16 at 19:41

3 Answers3

1

You can only use findFragmentById if the fragment was statically embedded in the XML within an activity and given an android:id.

In your case, it looks like that the fragment was dynamically added at runtime within an activity. So you can lookup this fragment by tag by calling findFragmentByTag on the FragmentManager. In your onNavigationItemSelected, you need to change to this:

public boolean onNavigationItemSelected(MenuItem item) {
  // Handle navigation view item clicks here.
  int id = item.getItemId();
  String TAG = "";
  Fragment fragment = null;
  if (id == R.id.nav_clicker) {
    fragment = new ClickerFragment();
    TAG = "CLICKER_TAG";
  } else if (id == R.id.nav_upgrades) {
    fragment = new UpgradeFragment();
    TAG = "UPDATE_TAG";
  }
  // You need to add TAG to another fragment.
  ...

  getSupportFragmentManager().beginTransaction(). 
              replace(R.id.frame_container, fragment, TAG).
              commit();
  ...
  return true;
}

Now you can lookup the fragment by tag:

ClickerFragment clickerFragment  = (ClickerFragment) getSupportFragmentManager()
                                                    .findFragmentByTag("CLICKER_TAG");
// Now you have the fragment
// But remember to check if the fragment null
if(clickerFragment != null) {
  ClickerFragment.refreshViews();
}

Read more at Creating and Using Fragments.

ישו אוהב אותך
  • 28,609
  • 11
  • 78
  • 96
0

Replace your MainActivity code with

ClickerFragment ClickerFragment = (ClickerFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.frame_container);
Manza
  • 3,427
  • 4
  • 36
  • 57
0

You can do this in your onNavigationItemSelected for all your Fragments if necessary

Fragment fragment = null;
String tag = null;
if (id == R.id.nav_clicker) {
    fragment = new ClickerFragment();
    tag = "ClickerFragment";
}
...
if (fragment != null) {
    FragmentManager fragmentManager = getSupportFragmentManager();
    //Add a tag parameter
    fragmentManager.beginTransaction()
        .replace(R.id.frame_container, fragment, tag).commit();
}

In your Refresh method do this

public void Refresh()
{
    ClickerFragment ClickerFragment = (ClickerFragment) getSupportFragmentManager().findFragmentByTag("ClickerFragment");
    ClickerFragment.refreshViews();
}
Veneet Reddy
  • 2,707
  • 1
  • 24
  • 40