简体   繁体   中英

Android Extract String from Okhttp onResponse Function

I would like to get String value from onResponse function in OkHttp3 using Android Studio, which is

final String title_name = jsonarray_news_extract_Data(jsonStr, index)

in below codes. I've tried insert String variable "a" in argument, but it said

Variable is accessed within inner class. Needs to be declared final

so that I declared as final then it said

Cannot Assign a Value to Final Variable

I tried to put

a = title_name;

after removed Handler method but still not work.

If you have any idea please help me out. Thank you

public void news_From_API_Title(String url_news, final int index, final TextView textView, String a){

    OkHttpClient client = new OkHttpClient();

    Request request = new Request.Builder()
            .url(url_news)
            .build();

    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(@NotNull Call call, @NotNull IOException e) {}

        @Override
        public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
            final String jsonStr = Objects.requireNonNull(response.body()).string();
            final String title_name = jsonarray_news_extract_Data(jsonStr, index);

            Handler mainHandler = new Handler(Looper.getMainLooper());
            mainHandler.post(new Runnable() {
                @Override
                public void run() {

                    a = title_name;
                }
            });
        }
    });

}

private String jsonarray_news_extract_Data(String jsonString_News, int index){
    try {
        JSONObject jsonObject = new JSONObject(jsonString_News);
        JSONArray jsonArray = jsonObject.getJSONArray("Data");
        return jsonArray.getJSONObject(index).getString("title");
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return null;
}

You can use a custom interface like this:

interface ApiCallback{
    void onOkHttpResponse(String data);
    void onOkHttpFailure(Exception exception);
}

Then you pass not a String but an instance of ApiCallback into the method which is actually doing the call:

public void news_From_API_Title(String url_news, final int index, final TextView textView, ApiCallback callback){

    OkHttpClient client = new OkHttpClient();

    Request request = new Request.Builder()
            .url(url_news)
            .build();

    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(@NotNull Call call, @NotNull IOException e) {
            callback.onOkHttpFailure(e);
        }

        @Override
        public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
            final String jsonStr = Objects.requireNonNull(response.body()).string();
            final String title_name = jsonarray_news_extract_Data(jsonStr, index);

            Handler mainHandler = new Handler(Looper.getMainLooper());
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    callback.onOkHttpResponse(title_name);
                }
            });
        }
    });

}

Now you can use an implementation of ApiCallback as follows:

String url_news = "https://some.web.address/news";
int index = 7;
TextView textView;
news_From_API_Title(url_news, index, textView, new apiCallback(){
    @Override
    public void onOkHttpResponse(String data){
        // do something with data here
        Log.d("TEST", "data = " + data);
    }

    @Override
    onOkHttpFailure(Exception exception){
        // exception handling
    }
});

Please note that it may be better from an architecture point of view if you don't pass the TextView as parameter into the method but instead set the text in onOkHttpResponse() :

// TextView will be initialized before calling news_From_API_Title()
// either make TextView a field (then use "private") 
// or declare it locally (then use "final")
private TextView textView;

// ... other code ...

String url_news = "https://some.web.address/news";
int index = 7;

// method will only take parameters which are not related to the UI 
// since it's desirable to avoid tight coupling of networking and UI components 
news_From_API_Title(url_news, index, new apiCallback(){
    @Override
    public void onOkHttpResponse(String data){
        // do something with data here
        // e.g. show data in TextView
        textView.setText(data);
    }

    @Override
    onOkHttpFailure(Exception exception){
        // exception handling
    }
});

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