简体   繁体   English

如何从onResponse返回值

[英]How do I return a value from onResponse

Basically this it the code structure, I would like to know how i can modify my codes so that I can get the value inside onResponse and returning it. 基本上,这就是代码结构,我想知道如何修改代码,以便可以在onResponse中获取值并返回它。 As of now, my mainReply variable return "(blank)" but im expecting it to pass the data in the arraylist called details inside my onResponse segment. 到目前为止,我的mainReply变量返回“(blank)”,但我希望它在我的onResponse段中的名为details的arraylist中传递数据。 Rest assure, there are values returned as I have checked, but i just cant get the value to be passed out of the onResponse segment. 请放心,我检查时有返回值,但我只是无法获取要传递给onResponse段的值。

I have checked for alternatives and they mentioned to use interface. 我检查了替代品,他们提到要使用接口。 However, I do not know how to modify my codes to use the solution that mentioned interface and use of callBacks. 但是,我不知道如何修改我的代码以使用提到的接口和callBacks的解决方案。

public class MainActivity extends AppCompatActivity {

    EditText et_message;
    FloatingActionButton fab_send;
    API api;
    ListView list_view_conversation;
    List<ChatModel> list_chat = new ArrayList<>();
    RevealDetailsCallbacks callback;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        et_message = (EditText) findViewById(R.id.et_message);
        fab_send = (FloatingActionButton) findViewById(R.id.fab_send);
        list_view_conversation = (ListView) findViewById(R.id.list_view_conversation);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(API.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        api = retrofit.create(API.class);

        fab_send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //this method ultimately is to get response and send back to user
                String s = et_message.getText().toString();
                ChatModel model = new ChatModel(s, true);
                list_chat.add(model);
                new retrieveDetails().execute(list_chat);

                et_message.setText("'");
            }
        });

    }

    public class retrieveDetails extends AsyncTask<List<ChatModel>, Void, String> {
        String text = et_message.getText().toString();
        String mainReply = "";
        List<ChatModel> models;
        List<String> details = new ArrayList<String>();

        @Override
        public String doInBackground(List<ChatModel>[] lists) {
            Call<List<Patient>> call = api.getPatients();
            models = lists[0];
            call.enqueue(new Callback<List<Patient>>() {
                public String reply;

                @Override
                public void onResponse(Call<List<Patient>> call, Response<List<Patient>> response) {
                    List<Patient> patients = response.body();

                    for (int i = 0; i < patients.size(); i++) {
                        if (patients.get(i).getNric().equals(text)) {
                            details.add("Name: " + patients.get(i).getName() + "\nNRIC: " + patients.get(i).getNric()
                                    + "\nDOB: " + patients.get(i).getDob() + "\nContact No: " + patients.get(i).getContactno());
                        }
                    }
                    this.mainReply = details.get(0);
                    Log.i("Here Log i", reply);
                }

                @Override
                public void onFailure(Call<List<Patient>> call, Throwable t) {
                    Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
                }
            });
            return mainReply;//I want to reply with the data added into the details arraylist in the onResponse segment
        }


        @Override
        public void onPostExecute(String s) {
            ChatModel chatModel = new ChatModel(s, false);
            models.add(chatModel);
            CustomAdapter adapter = new CustomAdapter(models, getApplicationContext());
            list_view_conversation.setAdapter(adapter);
        }
    }


}

If you wanted to modify your existing code, you would add an interface like the one I added up top (RevealDetailsCallbacks), pass it into the asynctask constructor, and run it. 如果要修改现有代码,则可以添加一个接口,就像我在顶部添加的接口(RevealDetailsCallbacks)一样,将其传递给asynctask构造函数,然后运行它。 The code would look like this: 代码如下所示:

public class MainActivity extends AppCompatActivity {

    //Interface callback here
    interface RevealDetailsCallbacks {
        public void getDataFromResult(List<String> details);
    }

    EditText et_message;
    FloatingActionButton fab_send;
    API api;
    ListView list_view_conversation;
    List<ChatModel> list_chat = new ArrayList<>();
    RevealDetailsCallbacks callback;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        et_message = (EditText) findViewById(R.id.et_message);
        fab_send = (FloatingActionButton) findViewById(R.id.fab_send);
        list_view_conversation = (ListView) findViewById(R.id.list_view_conversation);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(API.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        this.callback = new RevealDetailsCallbacks() {
            @Override
            public void getDataFromResult(List<String> details) {
                //Do stuff here with the returned list of Strings
            }
        };

        api = retrofit.create(API.class);

        fab_send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //this method ultimately is to get response and send back to user
                String s = et_message.getText().toString();
                ChatModel model = new ChatModel(s, true);
                list_chat.add(model);
                new retrieveDetails(callback).execute(list_chat);

                et_message.setText("'");
            }
        });

    }

    public class retrieveDetails extends AsyncTask<List<ChatModel>, Void, String> {
        String text = et_message.getText().toString();
        String mainReply = "";
        List<ChatModel> models;
        List<String> details = new ArrayList<String>();
        private RevealDetailsCallbacks listener;

        retrieveDetails(RevealDetailsCallbacks listener){
            this.listener = listener;
        }

        @Override
        public String doInBackground(final List<ChatModel>[] lists) {
            Call<List<Patient>> call = api.getPatients();
            models = lists[0];
            call.enqueue(new Callback<List<Patient>>() {
                public String reply;

                @Override
                public void onResponse(Call<List<Patient>> call, Response<List<Patient>> response) {
                    List<Patient> patients = response.body();

                    for (int i = 0; i < patients.size(); i++) {
                        if (patients.get(i).getNric().equals(text)) {
                            details.add("Name: " + patients.get(i).getName() + "\nNRIC: " + patients.get(i).getNric()
                                    + "\nDOB: " + patients.get(i).getDob() + "\nContact No: " + patients.get(i).getContactno());
                        }
                    }
                    this.mainReply = details.get(0);
                    Log.i("Here Log i", reply);
                    if(listener != null) {
                        listener.getDataFromResult(details);
                    }
                }

                @Override
                public void onFailure(Call<List<Patient>> call, Throwable t) {
                    //Don't make a toast here, it will throw an exception due to it being in doInBackground
                    //Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
                }
            });
            return mainReply;//I want to reply with the data added into the details arraylist in the onResponse segment
        }


        @Override
        public void onPostExecute(String s) {
            ChatModel chatModel = new ChatModel(s, false);
            models.add(chatModel);
            CustomAdapter adapter = new CustomAdapter(models, getApplicationContext());
            list_view_conversation.setAdapter(adapter);
        }
    }
}

However, there is no need for asynctask here since you are running Retrofit and calling .enqueue, which runs on a background thread. 但是,这里不需要asynctask,因为您正在运行Retrofit并调用在后台线程上运行的.enqueue。 A simpler version would look like this: 一个更简单的版本如下所示:

public class MainActivity extends AppCompatActivity {

    //Interface callback here
    interface RevealDetailsCallbacks {
        public void getDataFromResult(List<String> details);
    }

    //Keep your same variables here

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Same setup here

        this.callback = new RevealDetailsCallbacks() {
            @Override
            public void getDataFromResult(List<String> details) {
                //Do stuff here with the returned list of Strings
            }
        };


        fab_send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Same setup here, then call the method
                makeWebCalls();
            }
        });

    }

    private void makeWebCalls(){
        Call<List<Patient>> call = api.getPatients();
        models = lists[0];
        call.enqueue(new Callback<List<Patient>>() {
            @Override
            public void onResponse(Call<List<Patient>> call, Response<List<Patient>> response) {
                //Run your response code here. When done, pass to the callback
            }

            @Override
            public void onFailure(Call<List<Patient>> call, Throwable t) {
                Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

You can just enqueue the Retrofit call immediately in the OnClick and handle its response there 您可以立即在OnClick中加入Retrofit调用并在那里处理响应

fab_send.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            final String text = et_message.getText().toString();
            // if you're trying to filter data, add a parameter to getPatients() 
            api.getPatients().enqueue(new Callback<List<Patient>>() {
                 @Override
                 public void onResponse(Call<List<Patient>> call, Response<List<Patient>> response) {
                     // Here you have a full list of patients 
                     final List<Patient> patients = response.body();

                     // adapter = new PatientAdapter(MainActivity.this, patients);
                    // mListView.setAdapter(adapter);
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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