简体   繁体   中英

Java Interface with Default Inner Class

I am writing an android app that has two different background services, one to send and receive requests from a server, and one to download images from url's. Multiple pages of the app need to do these activities, so I wrote two interfaces, RequestReceiver for handling server requests, and ImageReceiver for downloading images.

To receive a broadcasted intent in Android, I am extending the BroadcastReceiver class and overriding its onReceive() method. This should be done via an inner class in the intent that calls a method in the class that implemented it. But, I can't call a non-static method from my static inner class.

public interface RequestReceiver {
    void handleRequest(int status, JSONObject object);

    class Receiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            int status = intent.getIntExtra("STATUS", -1);
            try {
                JSONObject object = new JSONObject(intent.getStringExtra("DATA"));
                handleRequest(status, object);
            } catch (JSONException e) {
                Log.e(this.toString(), "JSONException");
                e.printStackTrace();
            }
        }
    }
}

This doesn't compile:

non-static method cannot be referenced from a static context

What should I do differently?

EDIT: The reason I can't use an abstract class is that I need multiple inheritance. Some activities need to be ImageDownloaders and not RequestReceivers, and vice versa. Also, the classes that are implementing this interface are already inheriting from other classes. Some are extending Fragment and others are extending Activity, but they both need access to these abilities. Thus, it must be an interface.

You could pass an object of the outer class, which contains the non-static method, into your static inner class. This could be done via a constructor or a setter method. The object that is passed in should be assigned to a member variable of the static inner class.

You could then call the non-static method using the object of the outer class that was passed into the static inner class constructor or setter.

You could do something like this:

public interface RequestReceiver {
    void handleRequest(int status, JSONObject object);

    class MyBroadcastReceiver extends BroadcastReceiver {

        private final RequestReceiver requestReceiver;

        public MyBroadcastReceiver(RequestReceiver requestReceiver) {
            this.requestReceiver = requestReceiver;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            int status = intent.getIntExtra("STATUS", -1);
            try {
                JSONObject object = new JSONObject(intent.getStringExtra("DATA"));
                requestReceiver.handleRequest(status, object);
            } catch (JSONException e) {
                Log.e(this.toString(), "JSONException");
                e.printStackTrace();
            }
        }
    }
}

I didn't try the code... so there might be some errors... but you get the idea

I should drink coffee before jumping into StackOverflow.

Anyway…

you're trying to access a non-static method from your static inner class (that's how Java works).

Although some methods to provide a workaround have been provided, this usually highlights a higher level architecture problem.

Why are you having a class inside an interface and why is this class a BroadcastReceiver?

Shouldn't you be trying to abstract this a little bit differently?

I would personally frown at such code. What is the intent you're trying to explain in your code? When I read this code, what am I supposed to infer from it? What's the intention of such interface?

Am I supposed to use this interface and care that there's a broadcast receiver in it?

I think you should reconsider writing this code differently, rather than try to fight the tools/language.

How would I approach your problem?

Multiple pages of the app need to do these activities

1) Send and receive requests from a server

2) Download images from url's

Why not create these implementations in an abstract classes that each activity can extend when they need such behavior. (You can interface the methods later if you really need them).

The details of each implementation doesn't really concern the children. Nor you want to change each activity should your "image downloader" code changes.

Re-think your problem :)

UPDATE:

I have the feeling you're lost in the "Object Oriented" world. I strongly recommend you take a look at this (old but still valid) book: Agile Software Development, Principles, Patterns, and Practices by Robert C. Martin.

Don't be fooled by its title tho, this is not a book about "Scrum meetings".

I don't know the implementation details about your problem in particular, but I suggest you re-think your design; image downloading and network request/response have nothing to do with activities per-se and should not have to be implemented by an activity through an interface.

You should consider having a more "Factory-Oriented" approach (And I hate naming "patterns" because I think they tend to "over-complicate" things).

Although I don't agree 100% with the suggestions made in this other book , I also recommend it. I've learned a few interesting things out of it and I think it's a prequel of the Agile one, written years later ;)

An Activity that has to make a request, should call your DAO (Data Access Object) and request for the data. The data may come from the network, may come from a local cache, may come from a local file, who knows. The activity certainly doesn't care. And it shouldn't.

Downloading an image from a URL is probably left to a simple and robust library like Picasso , but if you insist on writing your own, then, the implementation and usage should never be tied to a particular Activity .

Without any more information, it's hard to tell what exact problem you're facing and how you are trying to solve it.

Your particular problem (the non-static method error) is a clear indicator that you're trying to go towards a non-standard/hacky solution and you should take a couple of steps back before it's too late (as the second book I linked will happily explain) ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM