【问题标题】:How to access response value outside onResponse method in android如何在android中的onResponse方法之外访问响应值
【发布时间】:2017-06-15 03:53:29
【问题描述】:

我正在开发一个安卓项目。我得到了来自 google api 的响应并解析了 json。但是我想返回 onResponse 方法之外的值,这对我来说现在似乎是不可能的。下面是我的代码,我已经在这里看到了这个answer。但我希望这个值在这个异步方法之外。是否可以访问此值。

更新 - 我已更新我的代码以获取更多详细信息。这是我的完整活动课。你可以看到我想要达到的目标。请帮助我如何访问 Volley onResponse 在方法 get_time_to_travel 中返回的值,在方法 parseJson 中。这现在真的要死我了。我的第一个 android 项目,我从前两天被困在这里。

对此的任何帮助将不胜感激。

public class MainActivity extends AppCompatActivity {


    private RecyclerView recyclerView;
    private LinearLayoutManager linearLayoutManager;
    private CustomAdapter adapter;
    private List<UserData> userData;
    private LocationManager locationManager;
    private LocationListener locationListener;
    String origin, mode = "driving";
    private String API = "APIKey";
    TextView textView;
    RequestQueue requestQueue;
    RequestQueue requestQueue1;
    String url = "https://url/users";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
        recyclerView.setHasFixedSize(true);


        locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        locationListener = new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
                double lat = location.getLatitude();
                double lng = location.getLongitude();
                origin = String.valueOf(lat)+","+String.valueOf(lng);
            }

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {

            }

            @Override
            public void onProviderEnabled(String provider) {

            }

            @Override
            public void onProviderDisabled(String provider) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                startActivity(intent);
            }
        };
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{
                        Manifest.permission.ACCESS_FINE_LOCATION,
                        Manifest.permission.ACCESS_COARSE_LOCATION,
                        Manifest.permission.INTERNET
                }, 10);
            }
            return;
        }
        else{
            locationManager.requestLocationUpdates("gps", 5000, 0, locationListener);
        }


        getData();

        linearLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager);
        adapter = new CustomAdapter(this, userData);
        recyclerView.setAdapter(adapter);

    }

    private void getData(){
        userData = new ArrayList<>();
        requestQueue = Volley.newRequestQueue(this);

        JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(url,
                new Response.Listener<JSONArray>() {

                    @Override
                    public void onResponse(JSONArray response) {
                        parseJson(response);
                    }
                },

                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.e("VOLLEY", "ERROR");
                    }
                }
        );
        requestQueue.add(jsonArrayRequest);
    }

    private void parseJson(JSONArray response){
        try {
            for (int i = 0; i < response.length(); i++) {
                JSONObject users = response.getJSONObject(i);

                String id = ("id: "+users.getString("id"));
                String name = ("Name: "+users.getString("name"));
                String username = ("Username: "+users.getString("username"));
                String email = ("Email: "+users.getString("email"));
                String address = parseAddress(users);
                String destination = parseCoordinates(users);
                String company = parseCompany(users);
                String phone = ("Phone: "+users.getString("phone"));
                String website = ("Website: "+users.getString("website"));
                String eta = get_time_to_travel(origin, destination, API, mode);

                UserData udata = new UserData(id, name, username, email, address, phone, website, company,eta);
                userData.add(udata);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    private String parseAddress(JSONObject users) {
        JSONObject completeAdd = null;
        String address = null;
        try {
            completeAdd = users.getJSONObject("address");
            String street = completeAdd.getString("street");
            String suite = completeAdd.getString("suite");
            String city = completeAdd.getString("city");
            String zipcode = completeAdd.getString("zipcode");
            address = ("Address :" + street + ", " + suite + ", " + city + ", " + zipcode);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return address;
    }

    private String parseCoordinates(JSONObject users) {
        JSONObject completeAdd = null;
        String destination = null;
        try {
            completeAdd = users.getJSONObject("address");
            JSONObject coordinates = completeAdd.getJSONObject("geo");
            String latitude = coordinates.getString("lat");
            String longitude = coordinates.getString("lng");
            destination = latitude + "," + longitude;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return destination;
    }

    private String parseCompany(JSONObject users) {
        JSONObject companyDetail = null;
        String company = null;
        try {
            companyDetail = users.getJSONObject("company");
            String company_name = companyDetail.getString("name");
            String catchPhrase = companyDetail.getString("catchPhrase");
            String bs = companyDetail.getString("bs");
            company = ("Company: " + company_name + ", " + catchPhrase + ", " + bs);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return company;
    }


    private String get_time_to_travel(String origin, String destination, String API, String mode){
        requestQueue1 = Volley.newRequestQueue(this);
        String eta = null;
        String google_api = "https://maps.googleapis.com/maps/api/distancematrix/json?origins="+origin+"&destinations="
                +destination+"s&mode="+mode+"&language=fr-FR&key="+API;
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, google_api, null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        eta = parseGoogleData(response);
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.e("VOLLEY", "ERROR");
                    }
                }

        );
        requestQueue1.add(jsonObjectRequest);
        return eta;
    }

    private String parseGoogleData(JSONObject response) {
        String estimated_time_arrival = null;
        try {
            JSONArray rows = response.getJSONArray("rows");

            JSONObject elements = rows.getJSONObject(0);
            JSONArray elementsArr = elements.getJSONArray("elements");

            JSONObject durationObj = elementsArr.getJSONObject(0);
            JSONObject durationData = durationObj.getJSONObject("duration");
            estimated_time_arrival = durationData.getString("text");

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return estimated_time_arrival;
    }

}

【问题讨论】:

  • 你想访问哪里?
  • 我在我的主要活动中调用这个方法,我希望在主要活动中访问这个值。
  • 为什么不在onResponse方法里面做你想在执行onResponse方法后做的代码?
  • 要访问外部数据,您需要使用接口创建自定义侦听器
  • 因为我从其他 api 获取用户数据,我必须在同一张卡上显示用户数据和这个值。你也可以告诉我如何创建自定义监听器。

标签: java android asynchronous android-volley


【解决方案1】:

异步任务正在其他线程上工作。因此,如果您想访问该方法之外的任何变量,则需要等到任务完成。否则变量将为空。 eg: on on 响应方法

@Override
        public void onResponse(String response) {
            res=response;
            anyMethodtopassVar(DataType data);
        }

【讨论】:

  • 您可以通过我认为的响应方法传递值。使用方法。所以在完成任务后,该方法将被调用。 @Sinscary
【解决方案2】:

OnCreate()的activity中,去掉这两行

adapter = new CustomAdapter(this, userData);
recyclerView.setAdapter(adapter);

getData() 中删除这一行

userData = new ArrayList<>();

将它们放入parseJson(),如下所示:

private void parseJson(JSONArray response){
    try {

        if(userData==null){
            userData = new ArrayList<>();
        }else{
            userData.clear();
        }
        for (int i = 0; i < response.length(); i++) {
            JSONObject users = response.getJSONObject(i);

            String id = ("id: "+users.getString("id"));
            String name = ("Name: "+users.getString("name"));
            String username = ("Username: "+users.getString("username"));
            String email = ("Email: "+users.getString("email"));
            String address = parseAddress(users);
            String destination = parseCoordinates(users);
            String company = parseCompany(users);
            String phone = ("Phone: "+users.getString("phone"));
            String website = ("Website: "+users.getString("website"));
            String eta = get_time_to_travel(origin, destination, API, mode);

            UserData udata = new UserData(id, name, username, email, address, phone, website, company,eta);
            userData.add(udata);
        }

        if(adapter == null){
            adapter = new CustomAdapter(this, userData);
            recyclerView.setAdapter(adapter);
        }else{
            adapter.notifyDataSetChanged();
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

这样,当json调用完成时,parseJson()被调用。 并将数组解析为userData 后,适配器被初始化或通知。

编辑:

嗯,这不是最好的解决方案。但这只是我的想法 有点讨厌/肮脏。我不知道,但我认为它会完成这项工作

1- 您不必每次都重新初始化队列,因此在 get_time_to_travel() 中将该行从方法中删除:

requestQueue1 = Volley.newRequestQueue(this);

final int index参数添加到方法中并使其成为void

private void get_time_to_travel(String origin, String destination, String API, String mode, final int index){...

在这样的方法中制作onResponse()

public void onResponse(JSONObject response) {
    eta = parseGoogleData(response);
    userData.get(index).setEta(eta);//add this setter to your data object if not exist.
}

删除 return eta;

现在用空字符串初始化 udata 为 eta

UserData udata = new UserData(id, name, username, email, address, phone, website, company,"");
userData.add(udata);

修改parseJson()中对get_time_to_travel()的调用如下:

get_time_to_travel(origin, destination, API, mode, i);

当在 onResponse() 调用 get_time_to_travel() 时,对象将被修改以保存从 API 检索到的 eta

这很糟糕,有时可能会在所有对 google api 的调用完成之前通知adapter。所以这只是为了告诉你如何制作它

编辑2 解决方法是 为 eta 初始化带有标签“正在加载...”的 userData 对象

UserData udata = new UserData(id, name, username, email, address, phone, website, company,"Loading...");

并在get_time_to_travel()onResponse() 末尾通知适配器:

public void onResponse(JSONObject response) {
    eta = parseGoogleData(response);
    userData.get(index).setEta(eta);//add this setter to your data object if not exist.
    adapter.notifyDataSetChanged();
}

【讨论】:

  • 您认为get_time_to_travel 方法是否需要更改。因为我试过了,但仍然没有得到eta 值。
  • @Sinscary 是的,您需要更改它,这是对 Web 服务的另一个调用,并且通过回调返回响应,因此将其分配给 parseJson() 中的变量不正确,因为响应可能是还没有。
  • 这就是杀死我的原因。请告诉我一种方法可以实现这一目标。
  • @Sinscary 检查编辑,它不是最终没有测试,只是给你一些指导。
【解决方案3】:

您想在onResponse 中获取parseJson 的结果吗? 将parseJson的返回类型改为UserData,在try块中调用return userDate;,在catch块中调用return null;。这将帮助您从调用它的位置捕获 parseJson 的结果。 如果我没有正确理解您的问题,请告诉我。

【讨论】:

  • 不,我正确地得到了 parseJson 结果。我没有从get_time_to_travel 获得eta 值。
  • @Sinscary 在这种情况下,您的代码似乎没问题,您确定正确解析了 json 吗?确保检查 Android Studio 中的日志是否有任何 Json 异常,或使用 Log.d 在 get_time_to_travel 方法中记录 eta[0]。
  • 是的 json 被正确解析。请检查get_time_to_travel 方法,我在jsonParse 中调用它。这就是问题所在。
  • 嗨@Priyam,所以您认为有没有办法在方法get_time_to_travel 中访问onResponse 的响应。
【解决方案4】:
public void getString(final VolleyCallback callback) {
    StringRequest req = new StringRequest(Request.Method.GET, url, new     Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            res=response;
            callback.onSuccess(res);
        }
    }...
}}

public interface VolleyCallback{
    void onSuccess(String result);
}

现在在您的 mainactivity 中,您可以这样做。

public void onResume(){
super.onResume();
getString(new VolleyCallback(){
     @Override
     public void onSuccess(String res){
         ... //do something
     }
});

}

【讨论】:

  • 试过了,这个答案也被复制了。我认为 stackoverflow 不是复制粘贴答案。
  • 几个月前我用过这个,它对我有用。我从我的项目中复制了这段代码,因为我现在没有找到链接。
  • 如果你仔细阅读我的代码,你会发现我已经这样做了
  • 那你有没有尝试使用总线库,它也可以用来解决你的问题。
猜你喜欢
  • 2021-09-16
  • 1970-01-01
  • 1970-01-01
  • 2022-11-21
  • 1970-01-01
  • 1970-01-01
  • 2020-02-10
  • 2014-06-26
  • 2014-01-15
相关资源
最近更新 更多