单击时 setOnClickListener() 未完全执行
setOnClickListener() is not executing completely on single click
我正在尝试使用 View.setOnClickListener
在单击按钮时触发一段代码。
我的代码包括两个 OkHttp
请求到 Google 地方 API 其中 returns JSON 文件。我解析它们,然后调用使用 APIs.
提取的 phone 号码
现在,当我点击按钮时,代码只执行了一部分。 它执行第一个请求和returns我需要的地方的Place ID。但是,phone 呼叫未发出。
在使用 Logcat 时,我们可以看到提取了地点 ID,但是只有当我再次单击该按钮时,才会执行完整的代码并且我看到双重输出,即 phone 提取的数字被记录了两次。
请帮助我解决这个执行流程问题,并确保 单击足以请求 2 API,然后再进行调用。
下面是我的Activity
的onCreate
方法的代码
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkPerms(this);
simpleLocation = new SimpleLocation(this, true);
tv1 = findViewById(R.id.tv1);
tv2 = findViewById(R.id.tv2);
bt = findViewById(R.id.bt);
String apikey = getString(R.string.apikey);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
simpleLocation.beginUpdates();
final double latitude = simpleLocation.getLatitude();
final double longitude = simpleLocation.getLongitude();
tv1.setText(String.valueOf(latitude));
tv2.setText(String.valueOf(longitude));
ExecutorService ex = Executors.newFixedThreadPool(1);
final FutureTask<String> result1 = (FutureTask<String>) ex.submit(new Callable<String>() {
public String call(){
OkHttpClient client = new OkHttpClient();
Request request1 =new Request.Builder()
.url(URLBuilder1(latitude, longitude, apikey))
.get()
.build();
try{
Response response = client.newCall(request1).execute();
JSONObject jsonObject = new JSONObject(response.body().string());
pid = jsonObject.getJSONArray("results").getJSONObject(0).getString("place_id");
} catch (IOException | JSONException e) {
e.printStackTrace();
Log.d("JSON 1", e.getLocalizedMessage());
}
return pid;
}
});
try {
PID = result1.get();
Log.d("TAG", PID);
}
catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
final FutureTask<String> result2 = (FutureTask<String>) ex.submit(new Callable<String>() {
@Override
public String call() {
try {
OkHttpClient client = new OkHttpClient();
Request request2 = new Request.Builder()
.url(URLBuilder2(apikey, pid))
.get()
.build();
Response response = client.newCall(request2).execute();
JSONObject jsonObject = new JSONObject(Objects.requireNonNull(response.body()).string());
phone = jsonObject.getJSONObject("result").getString("international_phone_number");
phone = phone.replace(" ", "");
Log.d("TAG", phone);
}
catch (IOException | JSONException e){
e.printStackTrace();
}
return phone;
}
});
try {
phone = result2.get();
Log.d("TAG", phone);
}
catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
Log.d("TAG", phone);
Intent i = new Intent(Intent.ACTION_CALL);
i.setData(Uri.parse("tel:" + phone));
}
});
}
p.s。我是一名学生开发人员,仅在 2 个月前才开始 Java Android,因此非常感谢有关代码优化的任何提示或任何其他有关改进代码的提示。
你应该嵌套这两个请求。
所以首先你应该 运行 第一个请求。然后在分配 pid 变量后立即开始第二个请求。然后在您分配 phone 变量之后,您应该立即启动 phone 调用意图。就这么简单。第二个请求应该在第一个请求中。 Phone Call Intent 应该在第二个请求中。希望你能理解。
在您的代码中发生的是,在您收到 pid 之前,第二个请求也被执行。如果你能通过 Google
使用 Volley Library 就更好了
示例代码
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
context = this;
checkPerms(this);
simpleLocation = new SimpleLocation(this, true);
tv1 = findViewById(R.id.tv1);
tv2 = findViewById(R.id.tv2);
bt = findViewById(R.id.bt);
String apikey = getString(R.string.apikey);
bt.setOnClickListener(new View.OnClickListener() {@Override
public void onClick(View v) {
simpleLocation.beginUpdates();
final double latitude = simpleLocation.getLatitude();
final double longitude = simpleLocation.getLongitude();
tv1.setText(String.valueOf(latitude));
tv2.setText(String.valueOf(longitude));
ExecutorService ex = Executors.newFixedThreadPool(1);
final FutureTask < String > result1 = (FutureTask < String > ) ex.submit(new Callable < String > () {
public String call() {
OkHttpClient client = new OkHttpClient();
Request request1 = new Request.Builder().url(URLBuilder1(latitude, longitude, apikey)).get().build();
try {
Response response = client.newCall(request1).execute();
JSONObject jsonObject = new JSONObject(response.body().string());
pid = jsonObject.getJSONArray("results").getJSONObject(0).getString("place_id");
final FutureTask < String > result2 = (FutureTask < String > ) ex.submit(new Callable < String > () {@Override
public String call() {
try {
OkHttpClient client = new OkHttpClient();
Request request2 = new Request.Builder().url(URLBuilder2(apikey, pid)).get().build();
Response response = client.newCall(request2).execute();
JSONObject jsonObject = new JSONObject(Objects.requireNonNull(response.body()).string());
phone = jsonObject.getJSONObject("result").getString("international_phone_number");
phone = phone.replace(" ", "");
Log.d("TAG", phone);
Intent i = new Intent(Intent.ACTION_CALL);
i.setData(Uri.parse("tel:" + phone));
}
catch(IOException | JSONException e) {
e.printStackTrace();
}
return phone;
}
});
} catch(IOException | JSONException e) {
e.printStackTrace();
Log.d("JSON 1", e.getLocalizedMessage());
}
return pid;
}
});
}
});
}
或者您可以异步方式使用 OkHttp。例如:
ExecutorService ex = Executors.newFixedThreadPool(1);
ex.submit(new Runnable() {
public void run() {
OkHttpClient client = new OkHttpClient();
Request request1 = new Request.Builder()
.url(URLBuilder1(latitude, longitude, apikey))
.get()
.build();
client.newCall(request1).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
//logging
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
try {
JSONObject jsonObject = new JSONObject(response.body().string());
pid = jsonObject.getJSONArray("results").getJSONObject(0).getString("place_id");
Log.d("TAG", pid);
} catch (IOException | JSONException e) {
e.printStackTrace();
Log.d("JSON 1", e.getLocalizedMessage());
}
Request request2 = new Request.Builder()
.url(URLBuilder2(apikey, pid))
.get()
.build();
OkHttpClient client = new OkHttpClient();
client.newCall(request2).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 {
try {
JSONObject jsonObject = new JSONObject(Objects.requireNonNull(response.body()).string());
phone = jsonObject.getJSONObject("result").getString("international_phone_number");
phone = phone.replace(" ", "");
Log.d("TAG", phone);
Intent i = new Intent(Intent.ACTION_CALL);
i.setData(Uri.parse("tel:" + phone));
} catch (IOException | JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
});
注意:我没有运行上面的代码,只是举个例子。
您可以使用
而不是同步 运行 的 client.newCall(request1).execute();
client.newCall(request1).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
//if request fails then this method gets executed
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//response is coming as method parameter "response"
}
});
这是完全异步的。
我正在尝试使用 View.setOnClickListener
在单击按钮时触发一段代码。
我的代码包括两个 OkHttp
请求到 Google 地方 API 其中 returns JSON 文件。我解析它们,然后调用使用 APIs.
现在,当我点击按钮时,代码只执行了一部分。 它执行第一个请求和returns我需要的地方的Place ID。但是,phone 呼叫未发出。
在使用 Logcat 时,我们可以看到提取了地点 ID,但是只有当我再次单击该按钮时,才会执行完整的代码并且我看到双重输出,即 phone 提取的数字被记录了两次。
请帮助我解决这个执行流程问题,并确保 单击足以请求 2 API,然后再进行调用。
下面是我的Activity
onCreate
方法的代码
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkPerms(this);
simpleLocation = new SimpleLocation(this, true);
tv1 = findViewById(R.id.tv1);
tv2 = findViewById(R.id.tv2);
bt = findViewById(R.id.bt);
String apikey = getString(R.string.apikey);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
simpleLocation.beginUpdates();
final double latitude = simpleLocation.getLatitude();
final double longitude = simpleLocation.getLongitude();
tv1.setText(String.valueOf(latitude));
tv2.setText(String.valueOf(longitude));
ExecutorService ex = Executors.newFixedThreadPool(1);
final FutureTask<String> result1 = (FutureTask<String>) ex.submit(new Callable<String>() {
public String call(){
OkHttpClient client = new OkHttpClient();
Request request1 =new Request.Builder()
.url(URLBuilder1(latitude, longitude, apikey))
.get()
.build();
try{
Response response = client.newCall(request1).execute();
JSONObject jsonObject = new JSONObject(response.body().string());
pid = jsonObject.getJSONArray("results").getJSONObject(0).getString("place_id");
} catch (IOException | JSONException e) {
e.printStackTrace();
Log.d("JSON 1", e.getLocalizedMessage());
}
return pid;
}
});
try {
PID = result1.get();
Log.d("TAG", PID);
}
catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
final FutureTask<String> result2 = (FutureTask<String>) ex.submit(new Callable<String>() {
@Override
public String call() {
try {
OkHttpClient client = new OkHttpClient();
Request request2 = new Request.Builder()
.url(URLBuilder2(apikey, pid))
.get()
.build();
Response response = client.newCall(request2).execute();
JSONObject jsonObject = new JSONObject(Objects.requireNonNull(response.body()).string());
phone = jsonObject.getJSONObject("result").getString("international_phone_number");
phone = phone.replace(" ", "");
Log.d("TAG", phone);
}
catch (IOException | JSONException e){
e.printStackTrace();
}
return phone;
}
});
try {
phone = result2.get();
Log.d("TAG", phone);
}
catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
Log.d("TAG", phone);
Intent i = new Intent(Intent.ACTION_CALL);
i.setData(Uri.parse("tel:" + phone));
}
});
}
p.s。我是一名学生开发人员,仅在 2 个月前才开始 Java Android,因此非常感谢有关代码优化的任何提示或任何其他有关改进代码的提示。
你应该嵌套这两个请求。 所以首先你应该 运行 第一个请求。然后在分配 pid 变量后立即开始第二个请求。然后在您分配 phone 变量之后,您应该立即启动 phone 调用意图。就这么简单。第二个请求应该在第一个请求中。 Phone Call Intent 应该在第二个请求中。希望你能理解。
在您的代码中发生的是,在您收到 pid 之前,第二个请求也被执行。如果你能通过 Google
使用 Volley Library 就更好了示例代码
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
context = this;
checkPerms(this);
simpleLocation = new SimpleLocation(this, true);
tv1 = findViewById(R.id.tv1);
tv2 = findViewById(R.id.tv2);
bt = findViewById(R.id.bt);
String apikey = getString(R.string.apikey);
bt.setOnClickListener(new View.OnClickListener() {@Override
public void onClick(View v) {
simpleLocation.beginUpdates();
final double latitude = simpleLocation.getLatitude();
final double longitude = simpleLocation.getLongitude();
tv1.setText(String.valueOf(latitude));
tv2.setText(String.valueOf(longitude));
ExecutorService ex = Executors.newFixedThreadPool(1);
final FutureTask < String > result1 = (FutureTask < String > ) ex.submit(new Callable < String > () {
public String call() {
OkHttpClient client = new OkHttpClient();
Request request1 = new Request.Builder().url(URLBuilder1(latitude, longitude, apikey)).get().build();
try {
Response response = client.newCall(request1).execute();
JSONObject jsonObject = new JSONObject(response.body().string());
pid = jsonObject.getJSONArray("results").getJSONObject(0).getString("place_id");
final FutureTask < String > result2 = (FutureTask < String > ) ex.submit(new Callable < String > () {@Override
public String call() {
try {
OkHttpClient client = new OkHttpClient();
Request request2 = new Request.Builder().url(URLBuilder2(apikey, pid)).get().build();
Response response = client.newCall(request2).execute();
JSONObject jsonObject = new JSONObject(Objects.requireNonNull(response.body()).string());
phone = jsonObject.getJSONObject("result").getString("international_phone_number");
phone = phone.replace(" ", "");
Log.d("TAG", phone);
Intent i = new Intent(Intent.ACTION_CALL);
i.setData(Uri.parse("tel:" + phone));
}
catch(IOException | JSONException e) {
e.printStackTrace();
}
return phone;
}
});
} catch(IOException | JSONException e) {
e.printStackTrace();
Log.d("JSON 1", e.getLocalizedMessage());
}
return pid;
}
});
}
});
}
或者您可以异步方式使用 OkHttp。例如:
ExecutorService ex = Executors.newFixedThreadPool(1);
ex.submit(new Runnable() {
public void run() {
OkHttpClient client = new OkHttpClient();
Request request1 = new Request.Builder()
.url(URLBuilder1(latitude, longitude, apikey))
.get()
.build();
client.newCall(request1).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
//logging
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
try {
JSONObject jsonObject = new JSONObject(response.body().string());
pid = jsonObject.getJSONArray("results").getJSONObject(0).getString("place_id");
Log.d("TAG", pid);
} catch (IOException | JSONException e) {
e.printStackTrace();
Log.d("JSON 1", e.getLocalizedMessage());
}
Request request2 = new Request.Builder()
.url(URLBuilder2(apikey, pid))
.get()
.build();
OkHttpClient client = new OkHttpClient();
client.newCall(request2).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 {
try {
JSONObject jsonObject = new JSONObject(Objects.requireNonNull(response.body()).string());
phone = jsonObject.getJSONObject("result").getString("international_phone_number");
phone = phone.replace(" ", "");
Log.d("TAG", phone);
Intent i = new Intent(Intent.ACTION_CALL);
i.setData(Uri.parse("tel:" + phone));
} catch (IOException | JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
});
注意:我没有运行上面的代码,只是举个例子。
您可以使用
而不是同步 运行 的client.newCall(request1).execute();
client.newCall(request1).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
//if request fails then this method gets executed
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//response is coming as method parameter "response"
}
});
这是完全异步的。