安卓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.pswp.cn/bicheng/94135.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/94135.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/94135.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

一個狀態機如何啟動/停止另一個狀態機

一個狀態機如何啟動/停止另一個狀態機 這個過程主要依賴于動作列表&#xff08;Action List&#xff09; 中的特定動作項和狀態管理服務&#xff08;ARA::SM&#xff09;提供的API。 1. 通過動作列表&#xff08;Action List&#xff09;進行預配置控制 這是最常見的方式&#…

基于IPO智能粒子優化的IIR濾波器參數識別算法matlab仿真

目錄 1.程序功能描述 2.測試軟件版本以及運行結果展示 3.部分程序 4.算法理論概述 5.完整程序 1.程序功能描述 IIR&#xff08;Infinite Impulse Response&#xff09;濾波器即無限沖激響應濾波器&#xff0c;其輸出不僅與當前和過去的輸入有關&#xff0c;還與過去的輸出…

歐州服務器String 轉 double 有BUG?

string 轉 double 的常見問題通常與文化差異、格式解析或特殊值處理相關&#xff0c;而非框架本身的 “BUG”。以下是可能導致轉換異常的常見場景及解決方案&#xff1a; 文化差異導致的解析問題 現象&#xff1a;同樣的字符串&#xff08;如 “1.23” 或 “1,23”&#xff09;…

鴻蒙中網絡診斷:Network分析

上面的圖很熟悉吧 Network 面板的表格列出了所有請求&#xff0c;每一列都提供了關鍵信息&#xff1a; Name: 請求的資源名稱和路徑。 Status: HTTP 狀態碼&#xff08;診斷核心&#xff09;。200成功&#xff0c;304未修改&#xff08;緩存&#xff09;&#xff0c;404找不到…

HarmonyOS 實戰:6 種實現實時數據更新的方案全解析(含完整 Demo)

摘要 在當下的應用開發中&#xff0c;用戶體驗越來越依賴“實時性”。消息要第一時間送達、訂單狀態要立刻刷新、數據變化不能延遲……這些需求推動了“實時數據更新”成為應用的必備功能。在鴻蒙系統&#xff08;HarmonyOS&#xff09;中&#xff0c;我們既可以用系統內置的數…

第十六屆藍橋杯青少組C++省賽[2025.8.10]第二部分編程題(4、矩陣圈層交錯旋轉)

參考程序&#xff1a;#include <bits/stdc.h> using namespace std;const int MAXN 105; int a[MAXN][MAXN];int main() {int n;if (!(cin >> n)) return 0;for (int i 0; i < n; i)for (int j 0; j < n; j)cin >> a[i][j];int layers n / 2; // 每…

AI供應鏈情報預警 | 惡意Py包偽裝AI框架庫開展數據竊密及應用劫持攻擊

AI供應鏈情報概述近日&#xff08;18th Aug. , 2025&#xff09;&#xff0c;懸鏡安全情報中心在Python官方倉庫中捕獲1起偽裝成知名AI框架庫pytensor&#xff08;https://pypi.org/project/pytensor&#xff09;的組件投毒事件。在北京時間8月18日凌晨&#xff0c;投毒者連續發…

AI需要防火墻,云計算需要重新構想

Akamai創始人Tom Leighton欲終結云膨脹&#xff0c;從內到外守護AI安全 Akamai創始人Tom Leighton 當前超大規模云服務商主導著企業IT市場&#xff0c;鮮有人敢挑戰云計算經濟模式、AI基礎設施和網絡安全架構的現狀。但Akamai聯合創始人兼CEO Tom Leighton正是這樣的挑戰者。他…

線段樹詳解【數據結構】

簡介 線段樹是一種應用極其廣泛&#xff0c;使用范圍較廣并且非常知名的樹形數據結構&#xff0c;主要用于進行區間操作&#xff0c;如區間修改&#xff0c;區間查詢等。這種數據結構唯一的不足就是巨大的代碼量&#xff0c;因此處理一些較簡單的問題時建議用樹狀數組。 原理…

Maven 入門與進階:聚合、繼承與生命周期詳解

Maven 是 Java 項目管理的核心工具&#xff0c;其強大的依賴管理、項目構建和模塊化設計能力&#xff0c;極大地提升了開發效率。本文將深入探討 Maven 的 聚合&#xff08;Multi-module&#xff09;、繼承&#xff08;Inheritance&#xff09; 和 生命周期&#xff08;Lifecyc…

手搓MCP客戶端動態調用多MCP服務,調用哪個你說了算!

01 引言 前兩天&#xff0c;有個粉絲朋友咨詢MCP服務如何動態調用&#xff0c;動態加載MCP服務的鏈接&#xff1f;我們都知道MCP客戶端可以配置多個MCP服務的地址&#xff1a; spring.ai.mcp.client.sse.connections.server1.urlhttp://localhost:xxxx spring.ai.mcp.client.ss…

Go語言中的優雅并發控制:通道信號量模式詳解

在Go語言的并發編程中&#xff0c;“通過通信共享內存”的設計哲學貫穿始終。當面對高并發場景時&#xff0c;無限制創建goroutine可能導致資源耗盡、CPU過載等問題&#xff0c;通道信號量模式&#xff08;Channel Semaphore Pattern&#xff09; 正是一種基于Go通道特性的優雅…

鴻蒙 NEXT開發中輕松實現人臉識別功能

大家好&#xff0c;我是 V 哥。 今天給大家介紹在 HarmonyOS 原生鴻蒙開發中&#xff0c;實現人臉識別功能&#xff0c;這個功能在常用的 APP 開發中上鏡率還是很高的&#xff0c;在傳統的 Android 或 iOS 開發中&#xff0c;通常我們要借助第三方庫來實現&#xff0c;而在鴻蒙…

華為開發者空間訓練營-優秀作品公布

排名標題總分獎品1手把手教你開發一個地區智能查詢MCP&#xff0c;賦能地理位置類MCP服務的“零輸入”無感交互95華為 freebuds 6i 藍牙耳機2基于華為開發者空間云主機DeepSeek助力電商企業AI海報文案驅動的最佳實踐落地 94華為 freebuds 6i 藍牙耳機32小時基于華為開發者空間和…

基于Python與Tkinter開發的微博多功能自動化助手

文章目錄 摘要 1. 背景與意義 2. 需求分析 3. 核心架構設計 3.1. 技術選型 3.2. 核心思想:UI與邏輯分離的異步架構 4. 深度模塊化剖析 4.1. 微博核心API交互模塊 4.2. 健壯性設計:代理與重試機制 4.3. GUI界面模塊 (WeiboApp 類) 4.4. 異步任務處理模塊 5. 難點分析與解決方案…

效果驅動復購!健永科技RFID牛場智能稱重項目落地

近日&#xff0c;北京某養殖企業持續下單電子耳標識讀器&#xff0c;在牛場智能稱重中落地應用&#xff0c;通過自動、準確地識別牛只并記錄體重數據&#xff0c;顯著提升效率和數據精準度&#xff0c;實現了“效果驅動復購”的良性循環。健永科技RFID技術在北京某養殖企業智能…

計算機網絡:2、TCP和UDP

2、TCP和UDP 簡介 TCP(transmission Control Protocol)&#xff1a;是一種通信標準&#xff0c;它使應用程序和計算設備能夠在網絡上交換消息。它的設計目的是在互聯網上發送數據包&#xff0c;并確保數據和信息在網絡上的成功傳遞。UDP(the User Datagram Protocol)&#xf…

WEB安全篇:瀏覽器攻擊原理及防護

1、XSS&#xff1a;跨站腳本攻擊就是攻擊者想盡一切辦法將可以執行的代碼注入到網頁中。攻擊者在web頁面惡意插入HTML或script標簽&#xff0c;當用戶瀏覽該頁面時&#xff0c;惡意代碼就會被執行&#xff0c;從而達到攻擊的目的。XSS利用的是用戶對指定網站的信任。比如&#…

匯編語言學習2---GNU Debugger (GDB)

學習記錄&#xff0c;在匯編語言 &#xff0c;我們面對的是機器碼&#xff08;以匯編指令形式展現&#xff09;&#xff0c;所以斷點要設置在機器碼被加載到內存中的位置。 GEF插件使用 安裝插件wget -O ~/.gdbinit-gef.py -q https://gef.blah.cat/pyecho source ~/.gdbinit-g…

談談架構的內容

一、架構的定義架構是一個界定不清的東西&#xff0c;我們很難講清楚哪些東西是架構&#xff0c;哪些東西不是架構。但軟件行業里其實人人都在搞架構&#xff0c;軟件設計就是架構本身。架構這個詞出現得很早&#xff0c;有些人認為是 NASA&#xff08;也可能是NATO&#xff09…