“Standard simple” interfaces in Java?

▼魔方 西西 提交于 2019-12-24 06:07:09

问题


So here in Java I've written a typical class, to send json to a rest server. (I'll include the whole class below for clarity.) So that's a file "Fetcher.java"

Now for the callback you need an interface. The interface is trivial, just one function with a string.

public interface FetcherInterface {
    public void fetcherDone(String result);
}

Annoyingly you need a whole file for that, "FetcherInterface.java"

So this interface is nothing but "one callback with a string". Often all you need is just "one callback with no arguments".

In fact ........ are there some sort of standard interfaces I can use, or something like that?

It seems kind of annoying to have to put in a whole interface for such a simple "standard" interface.

What's the deal on this? What's the javaly solution?

It seems you CAN NOT put it in the same file:

Perhaps I misunderstand something there. If you could put it in the same file, that would be convenient at least.

(Lambdas are not yet practically available. Anyway, sometimes you want an interface.)


Just for clarity, here's how you call the class

    JSONObject j = new JSONObject();
    try {
        j.put("height", 2.1);
        j.put("width", 2.5);
        j.put("command", "blah");
    } catch (JSONException e) {
        e.printStackTrace();
    }
    new Fetcher("mobile/login", j, new FetcherInterface() {
                @Override
                public void fetcherDone(String result) {
                    Log.d("DEV","all done");
                    doSomething(result);
                }
        }
    ).execute();

or indeed

public class HappyClass extends Activity implements FetcherInterface {
...

private void someCall() {
    JSONObject j = new JSONObject();
    try {
        j.put("height", 2.1);
        j.put("width", 2.5);
        j.put("command", "blah");
    } catch (JSONException e) {
        e.printStackTrace();
    }
    new Fetcher("mobile/data", j, this).execute();
    devBlank();
}

@Override
public void fetcherDone(String result) {
    Log.d("DEV","all done" +result);
    doSomething(result);
}

Here's the whole class... Fetcher.java file

public class Fetcher extends AsyncTask<Void, Void, String> {

    private String urlTail;
    private JSONObject jsonToSend;
    private FetcherInterface callback;

    // initializer...
    Fetcher(String ut, JSONObject toSend, FetcherInterface cb) {
        urlTail = ut;
        jsonToSend = toSend;
        callback = cb;
    }

    @Override
    protected String doInBackground(Void... params) {

        HttpURLConnection urlConnection = null; // declare outside try, to close in finally
        BufferedReader reader = null;           // declare outside try, to close in finally
        String rawJsonResultString = null;
        String json = jsonToSend.toString();

        Log.d("DEV","the json string in Fetcher is " +json);

        try {
            URL url = new URL("https://falcon.totalfsm.com/" + urlTail);

            Log.d("DEV","the full URL in Fetcher is " +url);

            // open a json-in-the-body type of connection.......
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("POST");
            urlConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setConnectTimeout(5000);
            // urlConnection.setDoOutput(false); // can be important?

            urlConnection.connect();

            OutputStream os = urlConnection.getOutputStream();
            os.write(json.getBytes("UTF-8"));
            os.close();

            // annoyingly, you have to choose normal versus error stream...
            InputStream inputStream;
            int status = urlConnection.getResponseCode();
            if (status != HttpURLConnection.HTTP_OK)
                inputStream = urlConnection.getErrorStream();
            else
                inputStream = urlConnection.getInputStream();
            if (inputStream == null) { // nothing to do.
                return null;
            }

            StringBuffer buffer = new StringBuffer();
            reader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while ((line = reader.readLine()) != null) { // adding newlines makes debugging easier
                buffer.append(line + "\n");
            }

            if (buffer.length() == 0) { // stream was empty
                return null;
            }

            rawJsonResultString = buffer.toString();
            return rawJsonResultString;

        } catch (IOException e) {
            Log.e("PlaceholderFragment", "Error ", e);
            return null;
        } finally{
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (final IOException e) {
                    Log.e("PlaceholderFragment", "Error closing stream", e);
                }
            }
        }
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        Log.d("DEV", "Fetcher done");
        if (s==null) {
            Log.d("DEV","applying anti-null measures in Fetcher!");
            s = "message from app communications layer: 'null' returned from servers for that call at " +urlTail;
        }
        callback.fetcherDone(s);
    }
}

回答1:


I feel bad answering my own question, but as there were no other answers this info may be helpful.

DaveNewton and Rowtang have supplied the exact answers here:

(Point 1) If you want a genuinely public interface, it goes in its own file. That's how Java works. There's no alternative.

(Point 2) Normally, use protected interface and declare the interface inside the class. It can then be used throughout the app.

So...

public class Fetcher extends AsyncTask<Void, Void, String> {

    protected interface FetcherInterface {
        public void fetcherDone(String result);
    }

    private String urlTail;
    private JSONObject jsonToSend;
    private FetcherInterface callback;

    Fetcher(String ut, JSONObject toSend, FetcherInterface cb) {
        urlTail = ut;
        jsonToSend = toSend;
        callback = cb;
    }

    @Override
    protected String doInBackground(Void... params) {
    ....

(c# programmers would maybe call it "IFetcher".)



来源:https://stackoverflow.com/questions/41042283/standard-simple-interfaces-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!