主线程控制ProgressDialog的可见性

本文介绍了一个使用Android中Looper和Handler实现线程间通信的例子。通过创建自定义的Activity,利用按钮触发后台线程任务,并将结果显示在界面上。文章详细展示了如何设置UI组件、初始化线程以及消息传递的过程。
貌似这个看起来比较合理:

package com.example;

import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class Looper_8 extends Activity implements OnClickListener {
private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
private final int FP = LinearLayout.LayoutParams.FILL_PARENT;
private ProgressDialog progressDialog = null;
private myThread th1;
public TextView tv;
private Button btn, btn2;
private EventHandler h;

public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);

btn = new Button(this);
btn.setId(101);
btn.setBackgroundResource(R.drawable.icon);
btn.setText("test looper");
btn.setOnClickListener(this);
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(100, 50);
param.topMargin = 10;
layout.addView(btn, param);

btn2 = new Button(this);
btn2.setId(102);
btn2.setBackgroundResource(R.drawable.icon);
btn2.setText("exit");
btn2.setOnClickListener(this);
layout.addView(btn2, param);

tv = new TextView(this);
tv.setTextColor(Color.WHITE);
tv.setText("");
LinearLayout.LayoutParams param2 = new LinearLayout.LayoutParams(FP, WC);
param2.topMargin = 10;
layout.addView(tv, param2);
setContentView(layout);
// ------------------------
}

public void onClick(View v) {
switch (v.getId()) {
case 101:
progressDialog = ProgressDialog.show(this, "please wait…",
"Loading", true);
//生成主线程的handle
h = new EventHandler(Looper.myLooper());
th1 = new myThread();
th1.start();
break;
case 102:
finish();
break;
}
}

// ------------------------------------------------
public class EventHandler extends Handler {
public EventHandler(Looper looper) {
super(looper);
}

@Override
public void handleMessage(Message msg) {
progressDialog.dismiss();
setTitle((String) msg.obj);
}
}

// ---------------------------------------
class myThread extends Thread {
@Override
public void run() {
try {
sleep(6000); // 故意延遲
} catch (Exception e) {
e.printStackTrace();
}
String obj = "mainThread....";
Message m = h.obtainMessage(1, 1, 1, obj);
h.sendMessage(m);
}
}
}

flowchart TD A[用户在Activity点击按钮] --> B[主线程启动子线程(避免UI阻塞,防止ANR)] B --> C[主线程显示ProgressDialog:“软件正在生成中 请稍等...”] C --> D[子线程调用FileUtils.copyAssetsToFile: - 输入:当前Activity、Assets内模板文件“dc.zip” - 输出:复到ROOT_DIR(外部存储根目录)/dc.zip - 校验:判断目标文件是否已存在,存在则覆盖] D -->|抛出IOException(如Assets文件不存在/存储权限被拒)| Z[子线程捕获异常→主线程显示错误对话框:“生成失败:{IO异常信息}”] D --> E[子线程显示ProgressDialog:“验证传入图片合法性...”] E --> F[子线程初始化支付码检测: 1. 前置校验:BaseLockActivity已通过CheckPayQrCode.init(Context)初始化上下文 2. 实例化CheckPayQrCode:传入背景图片路径(bjlj.getText().toString()) 3. 调用checkPay2code()开始检测] F --> F1[checkPay2code()内部流程1:删除历史debug目录 - 调用deleteDebugDir()→获取sAppContext的ExternalFilesDir/debug - 目录存在则递归删除(deleteDirRecursively()),不存在则打印日志] F1 --> F2[checkPay2code()内部流程2:按顺序检测支付码(任一命中即抛异常) - ① 检测微信支付码:调用hasWeChatPay()→WeChatPay.containsWeChatPay() - 读取图片→缩放至1024px→ZXing解析→判断是否含“wechatpay/wxp:///weixin://” - 检测耗时记录+日志打印,命中则抛UnsupportedPayQrCodeException(WECHAT_PAY类型) - ② 未命中则检测支付宝码:调用hasAliPay()→AlipayCode.containsAlipay() - 同样ZXing解析,命中则抛异常(Alipay类型) - ③ 未命中则检测QQ钱包码:调用hasQQWallet()→QQWalletCode.containsQQWallet() - 命中则抛异常(QQ_Wallet类型) - ④ 未命中则检测微信小程序/赞赏码:调用hasWeChatMiniAppCode() - 启动子线程(CountDownLatch同步)→MiniAppQrcode.processImage() - 先ZXing识别,失败则检测定位点(需≥3个)+核心区/头像/Logo,命中则抛异常(WECHAT_MINI_APP类型)] F2 -->|检测到任一支付码(抛UnsupportedPayQrCodeException)| Z F2 -->|未检测到支付码,打印总耗时日志| G[子线程显示ProgressDialog:“复资源文件成功 正在解密资源包...”] G --> H[子线程调用FileUtils.decryptAndUnpack: - 输入:assets/dc.zip、解密密钥、目标目录WORK_DIR(ROOT_DIR/闪电博士生成器) - 操作:1. 对称解密dc.zip文件 2. 解压解密后的文件到WORK_DIR - 校验:解压后检查WORK_DIR是否存在res、resources.arsc等核心目录/文件] H -->|解密失败(密钥错误)/解压失败(压缩包损坏)| Z H --> I[子线程显示ProgressDialog:“解密资源包成功 替换软件图标及背景并删除原签名...”] I --> J[子线程调用FileUtils.copyImageFiles替换软件图标: - 输入:用户选择的图标路径(tblj.getText().toString())、目标路径WORK_DIR/res/drawable/ic_launcher.png - 校验:1. 源文件是否为图片格式(png/jpg) 2. 目标目录是否存在,不存在则创建 3. 读写权限判断] J -->|图片格式错误/路径不存在| Z J --> K[子线程调用FileUtils.copyImageFiles替换软件背景: - 输入:用户选择的背景路径(bjlj.getText().toString())、目标路径WORK_DIR/res/drawable/sd.png - 校验:同图标替换逻辑] K -->|图片格式错误/路径不存在| Z K --> L[子线程显示ProgressDialog:“写入密码及内容...”] L --> M[子线程调用writeEncryptedPasswords()写入加密数据到WORK_DIR/res/raw: 1. 处理密码(passwordEdits[0]:用户输入的密码框): - 调用sf.computeHash()计算密码哈希→转16进字符串→写入mm.txt 2. 处理内容(passwordEdits[1]:用户输入的内容框): - 调用TextUtil.encode(),以“闪”为密钥加密内容字节→写入nr.txt 3. 处理追溯数据(pz文件): - 拼接内容:“内容:{nr}+密码:{mm}+设备ID:{Settings.Secure.ANDROID_ID}” - 以空字符为密钥加密→写入pz文件 - 校验:确保res/raw目录存在,文件写入成功后刷新目录] M -->|文件写入失败(如目录不存在)| Z M --> N[子线程判断音频编辑框(audioEdit)是否非空?] N -->|是| O[子线程调用FileUtils.copyImageFiles处理音频: - 输入:用户选择的音频路径(audioEdit.getText().toString())、目标路径WORK_DIR/res/raw/a.mp3 - 校验:1. 源文件是否为音频格式(mp3等) 2. 文件大小是否超限(避免打包失败) 3. 目标目录存在性] O -->|音频格式错误/路径不存在| Z O --> P[跳过音频处理] N -->|否| P P --> Q[子线程判断应用名编辑框(rjm)是否非空?] Q -->|是| R[子线程显示ProgressDialog:“正在更改应用名称...”] R --> S[子线程调用ArscFile.ArscAppName()修改应用名: - 输入:WORK_DIR/resources.arsc(资源表文件)、用户输入的应用名(rjm.getText().toString()) - 内部流程:1. 读取arsc文件→解析ResTable_header/ResStringPool 2. 定位“app_name”资源条目 3. 替换资源值→生成新的字符串池→保存修改后的arsc文件] S -->|arsc文件损坏/未找到app_name资源| Z S --> T[跳过应用名修改] Q -->|否| T T --> U[子线程删除原APK签名目录: - 调用FileUtils.deleteDirectory()→删除WORK_DIR/META-INF - 校验:目录存在则递归删除所有文件/子目录,不存在则打印“无需删除”日志] U -->|删除失败(如文件被占用)| Z U --> V[子线程显示ProgressDialog:“删除签名成功 正在打包...”] V --> W[子线程初始化ApkZipModeBuilder并调用build()打包: - 输入:源目录WORK_DIR、输出APK路径ROOT_DIR/闪电博士.apk - 打包逻辑: 1. 初始化ZipFile(读写+创建+截断模式) 2. 遍历res目录:按资源类型选择压缩模式(raw/dex/jar不压缩,drawable/layout/xml等Deflate压缩) 3. 处理根目录文件:AndroidManifest.xml压缩,resources.arsc/dex/so不压缩 4. 生成LocalFileHeader+CentralDirEntry,写入PK头(0x04034b50) 5. 刷新中央目录,校验EOCD签名(0x06054b50)] W -->|打包失败(如文件权限不足)| Z W --> X[子线程显示ProgressDialog:“签名中...”] X --> Y[子线程调用apksigner.Main.sign()进行APK签名: - 输入:当前Activity、待签名APK(闪电博士.apk)、输出APK(OUTPUT_APK=ROOT_DIR/锁机生成(闪电博士生成器).apk) - 签名配置:使用内置签名证书 - 校验:签名后检查输出APK是否存在,文件大小是否正常] Y -->|签名失败(如证书无效)| Z Y --> AA[子线程显示ProgressDialog:“删除残留...”] AA --> AB[子线程调用FileUtils.deleteDirectory()删除WORK_DIR: - 递归删除WORK_DIR下所有文件/子目录(包括res、resources.arsc等) - 校验:确保目录删除干净,避免残留占用存储] AB -->|删除残留失败| AC[打印“残留删除警告”日志,不中断流程] AB --> AC AC --> AD[子线程显示ProgressDialog:“成功生成...”] AD --> AE[子线程通知主线程显示成功对话框: - 标题:“成功” - 内容:“路径: {OUTPUT_APK}” - 按钮:“确定”→点击后关闭对话框] AE --> AF[主线程隐藏ProgressDialog] Z --> AF[主线程隐藏ProgressDialog→流程结束] AF --> AG[生成流程结束] 生成思维导图
最新发布
10-17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值