4

My menu option button is in a different class than the class that fetches HTTP data. And it's giving me "PhotoGalleryFragment is not an enclosing class" error for

new PhotoGalleryFragment.FetchItemsTask("top-rated").execute();

PhotoGalleryActivity.java - In here, I am trying to make it so when the "Top Rated Movie" button is pressed, it passes the "top-rated" argument for the FetchItemsTask to run and change the API url and change the returned JSON from "popular" to "top-rated"

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.topRatedMovies) {
            Toast.makeText(getApplicationContext(), "Top Rated Movie selected", Toast.LENGTH_LONG).show();

            new PhotoGalleryFragment.FetchItemsTask("top-rated").execute();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

PhotoGalleryFragment.java - In here, I'm trying to fetch the data.

public  class FetchItemsTask extends AsyncTask<Void,Void,List<MovieItem>> {
    private String mQuery;
    public FetchItemsTask(String query) {
        mQuery = query;
    }

    @Override
    protected List<MovieItem> doInBackground(Void... params) {
        return new MovieFetchr().fetchItems(mQuery);
    }

    @Override
    protected void onPostExecute(List<MovieItem> items) {
        mItems = items;
        for (int i = 0; i < mItems.size(); i++) {
        }
        setupAdapter();
    }

}

How would I fix something like this? Thanks.

Ben Wong
  • 691
  • 2
  • 19
  • 29

2 Answers2

4

To create an inner class, you need to do that from an instance of the outer class or make the inner class static:

So, create the instance within PhotoGalleryFragment:

public class PhotoGalleryFragment {       
    void createTask(String query) {
        new FetchItemsTask(query); //return it if you like, or just call execute here, doesn't matter
    }
}

Or:

public static class FetchItemsTask

But I think you will need to do the first option as setupAdapter is probably a method on PhotoGalleryFragment.

By creating within PhotoGalleryFragment, that gives the inner class a reference to a PhotoGalleryFragment which is how it is able to call methods on it.

Think of it as a silent constructor parameter and field which acts much like this code, only without you lifting a finger:

public class FetchItemsTask extends AsyncTask<Void,Void,List<MovieItem>> {

    private final PhotoGalleryFragment outer;

    public FetchItemsTask(PhotoGalleryFragment outer, //a reference to the outer is passed in automatically
        String query) {
        this.outer = outer; //and stored in this FetchItemsTask instance
    }

    @Override
    protected void onPostExecute(List<MovieItem> items) {
        outer.setupAdapter(); //then used when outer methods are invoked
    }

}
weston
  • 54,145
  • 21
  • 145
  • 203
0

It's not clear from sources you included, but it seems that FetchItemsTask is an inner class of PhotoGalleryFragment.

To fix it you should make FetchItemsTask static inner class i.e. change:

public class PhotoGalleryFragment extends Fragment {
    public  class FetchItemsTask extends AsyncTask<Void,Void,List<MovieItem>> {
        ...
    }
}

to

public class PhotoGalleryFragment extends Fragment {
    public static class FetchItemsTask extends AsyncTask<Void,Void,List<MovieItem>> {
        ...
    }
}

More details about inner classes you may find here https://stackoverflow.com/questions/20252727/is-not-an-enclosing-class-java

Community
  • 1
  • 1
lrother
  • 344
  • 5
  • 18