当前位置: 首页 > news >正文

安卓app、微信小程序等访问多个api时等待提示调用与关闭问题

安卓app、微信小程序访问webapi,将需要一时间,我们称之为耗时操作,其它诸如密集型计算、访问文件与设备等亦是如此。在这个期间我们应该跳出提示,告知用户正在等待,并且很多时候,在等待时不允许用户再对UI进行操作,直到耗时操作结束(无论是否成功,下同)
在安卓app中可以定义一个继承自Dialog的“等待对话框 WaItDialog”,并且设置setCanceledOnTouchOutside(false),如此会设置一个“遮罩层”,这样,当在耗时操作开始前开启(Show)WaItDialog直到结束关闭(dismiss),用户就不能点击UI了。
微信小程序可以直接用wx.showLoading与wx.hideLoading,并将mask设为true,实现类似功能。
当我们只有一个耗时操作时,问题很容易,但如果是多个呢?下面便讲解如何在进行多个耗时操作时,开关等待提示的问题。我们以访问api为例,假定以下场景,访问三个api,第一个get请求、第二个post请求、第三个故意访问一个不存在的api。当其中遇到错误时,应不能影响其它api的响应。所以我们需要先分别建立一个get请求的api与post请求的api。你可以任意语言来实现接口,我这里用传统的asp.net frameworks(visault studio 2019有asp.net core,可以跨平台,而frameworks只能在windows部署,请注意区分) 的一般处理程序(ashx)来实现。
第一个get请求的api

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;namespace WebApi
{/// <summary>/// HellloHandler 的摘要说明/// </summary>public class HellloHandler : IHttpHandler{public void ProcessRequest(HttpContext context){context.Response.ContentType = "text/plain";if ( context.Request.QueryString["name"]!=null){context.Response.Write("你好"+ context.Request.QueryString["name"].ToString());}else{context.Response.Write("Hello World");}}public bool IsReusable{get{return false;}}}
}

第二个post请求api
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WebApi
{
///
/// PostHandler 的摘要说明
///
public class PostHandler : IHttpHandler
{

    public void ProcessRequest(HttpContext context){context.Response.ContentType = "text/plain";// context.Response.Write("Hello World");if (context.Request.HttpMethod != "POST"){context.Response.Write("非法请求");return;}string name = context.Request.Form["name"];if (string.IsNullOrEmpty(name)){context.Response.Write(" hello Post");}else{context.Response.Write("post:"+name);}}public bool IsReusable{get{return false;}}
}

}
接下来,就可以实现微信小程序、安卓app的访问了。
微信小程序,是单线程的,实现较为简单,因为我们要访问三个api,所以总数设为3,然后定义m=0 当wx.request complete时m+1,当m>=3时表示,所以三个api访问结束,调用 wx.hideLoading。注意在调试阶段,请勾选不校验合法域名选项。

  wxml代码
<!--pages/index/index.wxml-->
<view class="container">
<view>{{view1}}</view>
<view>{{view2}}</view>
<view>{{view3}}</view>
</view>

js代码,注意将接口地址替换为你自己实际的地址

Page({/*** 页面的初始数据*/data: {view1: '',view2: '',view3: '',errors: [] // 用于存储错误信息},/*** 生命周期函数--监听页面加载*/onLoad(options) {this.getMultipleApis();},completeCount: 3,m:0,gethelloapi() //get请求{var that=this;wx.request({url: 'http://192.168.2.102:59597/HellloHandler.ashx?name=Jim',success:function(res){var data=""if (res.statusCode==200){data=res.data}else{data="http错误:"+res.statusCode}console.log("get"+data)that.setData({view1:data,},)},fail:function(e){that.setData({view1:e.message})},complete:function(){that.m++;if (that.m>=that.completeCount){wx.hideLoading();}}},)},getpostoapi() //post请求{var that=this;wx.request({url: 'http://192.168.2.102:59597/PostHandler.ashx',method:"POST",header: {'content-type': 'application/x-www-form-urlencoded'  // 关键设置},data:{name:'WangHua',},success:function(res){var data=""if (res.statusCode==200){data=res.dataconsole.log("接收"+data)}else{data="http错误:"+res.statusCode}that.setData({view2:data,},console.log("应答"+res.statusCode))},fail:function(e){that.setData({view2:e.message})},complete:function(){that.m++;if (that.m>=that.completeCount){wx.hideLoading();}}},)},getnoexistapi() //不存在的请求{var that=this;wx.request({url: 'http://192.168.2.102:59597/NoExistHandler.ashx?name=Lucy',success:function(res){var data=""if (res.statusCode==200){data=res.data}else{data="http错误:"+res.statusCode}that.setData({view3:data,},console.log("应答"+res.statusCode))},fail:function(e){that.setData({view3:e.message})},complete:function(){that.m++;if (that.m>=that.completeCount){wx.hideLoading();}}},)},// 处理多个不同类型的API请求getMultipleApis() {// 显示加载提示wx.showLoading({title: '加载中...',mask: true});this.gethelloapi();this.getpostoapi();this.getnoexistapi();}})

接下来安卓app代码,安卓不允许在主线程,要用分线程来调用,分线程又不能操控UI,另外分线程还有考虑共享资源的安全访问,所以情况要比微信小程序复杂多,在编写代码前我们要做一些准备设置。
第一步要在AndroidManifest添加相关网络权限。



并且因为是调试下进行,还要application节点下,设置android:usesCleartextTraffic=“true”(默认网络访问必须https,ftps等有ssl的接口,设置此选项后可以解除限定)。
第二步,在Build.gradle引入okthhp(用来访问网络)、我封装好的WaitDialog.aar的包以及Glide (我在WaitDialog引用了Glide ,一个图片加载库)。
做完准备设置,就是代码了
布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="get api"android:id="@+id/BtnApi"/>
<TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/TV1"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/TV2"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/TV3"/></LinearLayout>

Java代码,这里有两个要注意的地方,前面也提及过。一是分线程不能操作UI,要在runOnUiThread中操作,二是,分线程安全访问共享资源的问题,我们不能直接像微信小程序一样m++来增加“计数器”。我们可以通过AtomicInteger类实现安全访问共享资源,实现类似m++的功能,以上两点代码都会体现。
package person.yin.mutiapi;

import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;import org.json.JSONObject;import java.io.IOException;
import java.io.StringWriter;
import java.util.concurrent.atomic.AtomicInteger;import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.CookieJar;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import swaddle.yinzhenwei.waitdialog.WaitDialog;public class MainActivity extends AppCompatActivity implements View.OnClickListener{private WaitDialog waitDialog;private Button btnapi;private String TAG="APITest";private TextView tv1;private  TextView tv2;private  TextView tv3;private AtomicInteger requestCounter = new AtomicInteger(0);private static final int apicount=3; //最大三个api访问@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv1=findViewById(R.id.TV1);tv2=findViewById(R.id.TV2);tv3=findViewById(R.id.TV3);findViewById(R.id.BtnApi).setOnClickListener(this);}//***************private  void test(){waitDialog=new WaitDialog(this);waitDialog.setText("查询中,稍候");waitDialog.show();waitDialog.show();requestCounter.set(0);gethelloapi("Bill",tv1);getpostapi("Bob",tv2);getnoexistapi("Liu",tv3);}private void gethelloapi(String name,TextView tv) //访问helloapi get请求{OkHttpClient client = new OkHttpClient.Builder().build();RequestBody rbody = new FormBody.Builder().add("username", "admin").add("password", "12345").build();Request request = new Request.Builder().url("http://192.168.2.102:59597/HellloHandler.ashx?name="+name).post(rbody)
//                .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36")
//                .header("Accept", "text/plain") // 匹配服务器响应类型
//                .header("Connection", "close") // 避免长连接问题.build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.e(TAG, "请求失败: " + e);// e.printStackTrace();// 获取完整的堆栈信息StringWriter sw = new StringWriter();//e.printStackTrace(new PrintWriter(sw));Log.e(TAG, "完整异常信息: " + sw.toString());runOnUiThread(() ->{tv.setText("网络出现错误: " + e.getMessage());requestCounter.incrementAndGet();checkAllRequestsCompleted();});}@Overridepublic void onResponse(Call call, Response response) throws IOException {// 打印完整的响应信息用于调试Log.d(TAG, "收到响应: " + response.code());if (!response.isSuccessful()) {String errorBody = response.body() != null ? response.body().string() : "无响应体";Log.e(TAG, "HTTP错误 " + response.code() + ": " + errorBody);runOnUiThread(() ->{tv.setText("HTTP错误: " + response.code() );requestCounter.incrementAndGet();checkAllRequestsCompleted();});return;}String responseData = response.body().string();Log.d(TAG,  responseData);runOnUiThread(() ->{//textViewResult.setText( responseData);tv.setText(responseData);requestCounter.incrementAndGet();checkAllRequestsCompleted();});}});}private void getnoexistapi(String name,TextView tv) //故意访问一个不存在api{OkHttpClient client = new OkHttpClient.Builder().build();RequestBody rbody = new FormBody.Builder().add("username", "admin").add("password", "12345").build();Request request = new Request.Builder().url("http://192.168.2.102:59597/NoExistHandler.ashx?name="+name).post(rbody)
//                .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36")
//                .header("Accept", "text/plain") // 匹配服务器响应类型
//                .header("Connection", "close") // 避免长连接问题.build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.e(TAG, "请求失败: " + e);// e.printStackTrace();// 获取完整的堆栈信息StringWriter sw = new StringWriter();//e.printStackTrace(new PrintWriter(sw));Log.e(TAG, "完整异常信息: " + sw.toString());runOnUiThread(() ->{tv.setText("网络出现错误: " + e.getMessage());requestCounter.incrementAndGet();checkAllRequestsCompleted();});}@Overridepublic void onResponse(Call call, Response response) throws IOException {// 打印完整的响应信息用于调试Log.d(TAG, "收到响应: " + response.code());Log.v(TAG,"ok");if (!response.isSuccessful()) {String errorBody = response.body() != null ? response.body().string() : "无响应体";Log.e(TAG, "HTTP错误 " + response.code() + ": " + errorBody);runOnUiThread(() ->{tv.setText("HTTP错误: " + response.code() );requestCounter.incrementAndGet();checkAllRequestsCompleted();});return;}String responseData = response.body().string();Log.d(TAG,  responseData);runOnUiThread(() ->{//textViewResult.setText( responseData);tv.setText(responseData);requestCounter.incrementAndGet();checkAllRequestsCompleted();});}});}private void getpostapi(String name, TextView tv)  //访问postapi post请求{// 创建带调试信息的OkHttpClientOkHttpClient client = new OkHttpClient.Builder().build();RequestBody rbody = new FormBody.Builder().add("name", name).build();Request request = new Request.Builder().url("http://192.168.2.102:59597/PostHandler.ashx").post(rbody).build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.e(TAG, "请求失败: " + e);// e.printStackTrace();// 获取完整的堆栈信息StringWriter sw = new StringWriter();//e.printStackTrace(new PrintWriter(sw));Log.e(TAG, "完整异常信息: " + sw.toString());runOnUiThread(() ->{tv.setText("网络出现错误: " + e.getMessage());requestCounter.incrementAndGet();checkAllRequestsCompleted();});}@Overridepublic void onResponse(Call call, Response response) throws IOException {// 打印完整的响应信息用于调试Log.d(TAG, "收到响应: " + response.code());if (!response.isSuccessful()) {String errorBody = response.body() != null ? response.body().string() : "无响应体";Log.e(TAG, "HTTP错误 " + response.code() + ": " + errorBody);runOnUiThread(() ->{tv.setText("HTTP错误: " + response.code() );requestCounter.incrementAndGet();checkAllRequestsCompleted();});return;}String responseData = response.body().string();Log.d(TAG,  responseData);runOnUiThread(() ->{tv.setText( responseData);requestCounter.incrementAndGet();checkAllRequestsCompleted();});}});}private void checkAllRequestsCompleted() {if (requestCounter.get() >= apicount) {//runOnUiThread(this::dismissLoading);//runOnUiThread(()->waitDialog.dismiss());waitDialog.dismiss();}}@Overridepublic void onClick(View v){switch (v.getId()){case R.id.BtnApi:test();break;}}
}  	

至此所有代码均已完成,我打包了微信小程序和安卓app的代码,因为api接口可以用多种语言实现,就不打包了,如果需要复制黏贴吧。代码地址 https://download.csdn.net/download/wstcl/91725186?spm=1001.2014.3001.5503

http://www.xdnf.cn/news/1339327.html

相关文章:

  • QT QProcess, WinExec, ShellExecute中文路径带空格程序或者脚本执行并带参数
  • 灵活使用UE5 Modeling中的UV编辑功能
  • QT-初识
  • 日志收集(ELK)
  • javaweb开发笔记——微头条项目开发
  • 【笔记】Facefusion3.3.2 之 NSFW 检测屏蔽测试
  • Windows 系统中,添加打印机主要有以下几种方式
  • macos使用FFmpeg与SDL解码并播放H.265视频
  • Git常用操作大全(附git操作命令)
  • 【LeetCode】18. 四数之和
  • 微服务的编程测评系统13-我的竞赛列表-elasticSearch
  • javaweb开发笔记—— 前端工程化
  • Spring Boot 集成 Redis 发布订阅实现消息通信
  • 计算机网络技术学习-day6《三层交换机配置》
  • 01 网络信息内容安全--绪论
  • 2025.7.19卡码刷题-回溯算法-组合
  • Web 安全之 HTTP 响应截断攻击详解
  • 数据结构初阶:排序算法(三)归并排序、计数排序
  • 【数据结构】深入解析选择排序与堆排序:从基础到高效实现的完全指南
  • 深度卷积神经网络AlexNet
  • openEuler系统中r如何将docker安装在指定目录
  • 神经网络中 标量求导和向量求导
  • 如何通过传感器选型优化,为设备寿命 “续航”?
  • 机器学习6
  • RootDB:一款开源免费的Web报表工具
  • 0821 sqlite3_get_table函数(数据库函数的补充)
  • Vue.js 中使用 Highcharts 构建响应式图表 - 综合指南
  • 遥感机器学习入门实战教程|Sklearn案例⑤:集成学习方法全览
  • Python学习-- 数据库和MySQL入门
  • CentOS 7常用国内源配置:阿里云、腾讯云、华为云、清华源