0
The Goal

I'm trying to write a method that would replace the code that I use to swap fragments in order to keep copying and posting to a minimum (and to stay D.R.Y.)

The Problem

I get an error when I attempt to use the class that I passed in as an argument to create a new instance of that class.

The error occurs in this line of code, to the left of the operator (equal sign):

newFragmentClass new_fragment = newFragmentClass.newInstance();     

The error it gives me is: "newFragmentClass cannot be resolved to a type".

Full Code
    private void changeFragment(Class<?> newFragmentClass)
    {
        // Detect the current fragment
            Fragment current_fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
    
        // Create a new instance of the given class, edit later to gracefully handle errors
            newFragmentClass new_fragment = newFragmentClass.newInstance(); 
            
        // Switch to the new fragment
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.detach(current_fragment);
            transaction.replace(R.id.fragment_container, new_fragment);
            transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
            transaction.commit();
            
        // Change the tab background to indicate that the tab is active, reset backgrounds for any other tabs
            findViewById(R.id.page_one_tab).setBackgroundResource(R.drawable.menu_button_background_active);
            findViewById(R.id.page_two_tab).setBackgroundResource(R.drawable.menu_button_background);
            findViewById(R.id.page_three_tab).setBackgroundResource(R.drawable.menu_button_background);
    
    }
    
    // Page One Tab Button Functionality
    public void pageOneTab (View v)
    {
        // Change the fragment to SelectPlayersFragment
        changeFragment(Page_One_Fragment.class);
    }
Attempted Solutions

I've been searching StackOverflow and the internet at large for quite a while and have not been able to find a solution. A few topics like this one seemed as if they would resolve the problem, but then I ran into an error on the transaction.replace line that I could not find a fix for: "The method replace(int, Fragment) in the type FragmentTransaction is not applicable for the arguments (int, Object)".

Community
  • 1
  • 1
Kirk
  • 108
  • 1
  • 9
  • try this `newFragmentClass new_fragment = new newFragmentClass();` – Lia Pronina Aug 29 '13 at 07:45
  • @LiaPronina: When I try your suggestion it gives me the same error ("newFragmentClass cannot be resolved to a type") on both mentions of "newFragmentClass" instead of just the first – Kirk Aug 29 '13 at 08:18

4 Answers4

1

You probably want something like:

private Fragment changeFragment(Class<? extends Fragment> newFragmentClass)  {
    Fragment current_fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
    // Create a new instance of the given class, edit later to gracefully handle errors
    Fragment new_fragment = null;
    try {
         new_fragment = newFragmentClass.newInstance();
    } catch (InstantiationException e) {            
        throw new RuntimeException(e); // for some reason this fragment loading has failed so crash
    } catch (IllegalAccessException e) {            
        throw new RuntimeException(e);
    } 
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.detach(current_fragment);
    transaction.replace(R.id.fragment_container, new_fragment);
    // ...   
user
  • 86,916
  • 18
  • 197
  • 190
  • When I tried your solution I received the same error as I did on the other two similar answers (`"Unhandled Exception Type IllegalAccessException"`) on the line `Fragment new_fragment = newFragmentClass.newInstance();` – Kirk Aug 29 '13 at 08:28
  • 1
    @Kirk The `newInstance()` method throws two exception `InstantiationException` and `IllegalAccessException`. Do you handle this by either using a `try-catch` block or a `throws` clause on the method? – user Aug 29 '13 at 08:32
  • @Luksprong I'm rather new to Android/Java programming and do not have experience with try-catch or throws. When I tried your solution in Eclipse I did notice that it pointed out those two possible resolutions- I tried both. When I tried the try/catch solution I received an error on the transaction.replace line stating that "the local variable new_fragment has not been initialized". – Kirk Aug 29 '13 at 08:38
  • @Luksprong When I try the `throws` clause, at first it causes another error on the method call, but when I use the same solution for that error it resolves the problem. – Kirk Aug 29 '13 at 08:40
  • @Luksprong However, I think that because the code from @Andy Res is much simpler (especially with the `throw` clauses) I think I will accept his answer. If I could accept both answers I would. – Kirk Aug 29 '13 at 08:41
  • 1
    @Kirk No problem. I've edited my answer anyway with the full code of the try catch block. – user Aug 29 '13 at 08:43
1

Perhaps a more simpler solution would be to pass a Fragment as argument, instead of aClass, and use it to replace the current fragment. Also, you don't need to detach the current fragment, that is what replace() does for you.

Something like this:

public void changeFragment(Fragment fragment) {
    FragmentManager manager = getSupportFragmentManager();
    FragmentTransaction transaction = manager.beginTransaction();
    transaction.replace(R.id.fragment_container, fragment, "tag");
    transaction.commit();
    //.....
}

And you use it like this:

changeFragment(new Page_One_Fragment());
Andy Res
  • 15,963
  • 5
  • 60
  • 96
  • I'm using detach because I was having issues with my tabs and fragments behaving strangely whenever I would switch orientation inside of the activity. I would link to the topic where I came across that solution but I can't seem to find it in my history. Anyways, I am trying your solution now and will report back shortly. – Kirk Aug 29 '13 at 08:09
  • Your solution works. However, I did have to make a change from: `changeFragment(Page_One_Fragment.newInstance());` to `changeFragment(new Page_One_Fragment());`. – Kirk Aug 29 '13 at 08:13
  • I'm going to look over the other answers and test them out as well. While yours seems to be simplest solution, I would feel wrong about selecting it without checking/thinking about the others too. – Kirk Aug 29 '13 at 08:17
1

I think you want this:

private <T extends Fragment> void changeFragment(Class<T> newFragmentClass)
{
    ...
    // Create a new instance of the given class, edit later to gracefully handle errors
    T new_fragment = newFragmentClass.newInstance(); 
    ...
}
IsidroGH
  • 2,037
  • 19
  • 27
  • When I tried your solution I received an error: "Unhandled Exception Type IllegalAccessException" on the right side of the line `T new_fragment = newFragmentClass.newInstance();` – Kirk Aug 29 '13 at 08:25
  • Luksprog helped me to resolve the error that I was getting (see the comments for that answer). Thanks for the help. – Kirk Aug 29 '13 at 08:43
1

Because your "newFragmentClass' is only a parameter of method, it's not a type so you can not instance it. Follow my code to fix your problem

private <T extends Fragment> void changeFragment(Class<T> newFragmentClass)
    {
        // Detect the current fragment
            Fragment current_fragment = getSupportFragmentManager().findFragmentById(R.id.content);

        // Create a new instance of the given class, edit later to gracefully handle errors
            T new_fragment = newFragmentClass.newInstance(); 

        // Switch to the player select fragment
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.detach(current_fragment);
            transaction.replace(R.id.fragment_container, new_fragment);
            transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
            transaction.commit();

        // Change the tab background to indicate that the tab is active, reset backgrounds for any other tabs
            findViewById(R.id.page_one_tab).setBackgroundResource(R.drawable.menu_button_background_active);
            findViewById(R.id.page_two_tab).setBackgroundResource(R.drawable.menu_button_background);
            findViewById(R.id.page_three_tab).setBackgroundResource(R.drawable.menu_button_background);

    }
hieuxit
  • 697
  • 1
  • 5
  • 15
  • When I tried your solution I received an error: "Unhandled Exception Type IllegalAccessException" on the right side of the line `T new_fragment = newFragmentClass.newInstance();` – Kirk Aug 29 '13 at 08:27
  • 1
    Because in your Page_One_Fragment class you have another Constructor than usual constructor ( public Page_One_Fragment(){...}). This is not a common use. You can refer link http://www.androiddesignpatterns.com/2012/05/using-newinstance-to-instantiate.html to know deep. Hope this help. – hieuxit Aug 29 '13 at 08:38
  • Luksprog helped me to resolve the error that I was getting (see the comments for that answer). Thanks for the help. – Kirk Aug 29 '13 at 08:43