termux-gui 0.2.0

Rust bindings for Termux:GUI - Build Android GUI apps in Rust
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
# 🔧 Termux GUI Rust Demo 重构方案

## 📋 目录
1. [当前状态分析]#当前状态分析
2. [重构目标]#重构目标
3. [公共代码提取]#公共代码提取
4. [库结构设计]#库结构设计
5. [重构步骤]#重构步骤
6. [兼容性保证]#兼容性保证
7. [测试计划]#测试计划

---

## 📊 当前状态分析

### ✅ 已实现的组件(验证工作的)

| 组件 | 状态 | 示例文件 | 验证时间 |
|------|------|----------|----------|
| TextView | ✅ 正常 | button_demo.rs, checkbox_demo.rs, etc. | 已验证 |
| EditText | ✅ 正常 | input_demo.rs | 已验证 |
| Button | ✅ 正常 | button_demo.rs | 已验证 |
| Checkbox | ✅ 正常 | checkbox_demo.rs | 已验证 |
| Switch | ✅ 正常 | switch_demo.rs | 已验证 |
| RadioButton | ✅ 正常 | radio_demo.rs | 已验证 |
| RadioGroup | ✅ 正常 | radio_demo.rs | 已验证 |
| Spinner | ⚠️ 需修复 | spinner_demo.rs | 显示问题 |
| LinearLayout | ✅ 正常 | 所有demo | 已验证 |
| NestedScrollView | ✅ 正常 | spinner_demo.rs | 已验证 |

**工作的示例文件:**
- ✅ button_demo.rs - 按钮计数器
- ✅ checkbox_demo.rs - 多选框
- ✅ input_demo.rs - 文本输入
- ✅ radio_demo.rs - 单选按钮
- ✅ switch_demo.rs - 开关
- ⚠️ spinner_demo.rs - 下拉列表(需修复级联更新)
- ✅ test_events.rs - 事件处理

**测试文件(可能不工作):**
- ❓ test_minimal_spinner.rs
- ❓ test_spinner_cascade.rs
- ❓ test_spinner_debug.rs
- ❓ test_spinner_fullscreen.rs
- ❓ test_spinner_simple.rs

### 🔍 代码重复分析

每个示例文件都重复实现了以下函数:

```rust
// 出现 12 次
fn generate_random_address() -> String

// 出现 11 次  
fn bind_abstract_socket(name: &str) -> Result<UnixListener, Error>

// 出现 12 次
fn send_message(stream: &mut UnixStream, msg: &Value) -> Result<(), Error>

// 出现 12 次
fn read_message(stream: &mut UnixStream) -> Result<Value, Error>

// 出现 12 次
fn send_and_read(stream: &mut UnixStream, msg: &Value) -> Result<Value, Error>
```

**代码重复量:** 约 40-50 行 × 12 文件 = **480-600 行重复代码**

---

## 🎯 重构目标

### 主要目标

1. **消除代码重复** - 将公共函数提取到 `lib.rs`
2. **提供清晰的 API** - 创建易用的高层接口
3. **保持示例简洁** - 示例专注于展示组件用法
4. **不破坏现有功能** - 保证所有工作的示例继续工作
5. **便于扩展** - 为未来添加组件做准备

### 次要目标

1. 统一错误处理
2. 改进文档
3. 添加单元测试
4. 提供构建器模式(Builder Pattern)

---

## 📦 公共代码提取

### 第一阶段:核心通信层

```rust
// src/lib.rs 或 src/connection.rs

/// 核心通信模块
pub mod connection {
    use std::os::unix::net::{UnixListener, UnixStream};
    use std::io::{Read, Write, Error};
    use serde_json::Value;
    
    /// 生成随机socket地址
    pub fn generate_random_address() -> String { ... }
    
    /// 绑定抽象命名空间socket
    pub fn bind_abstract_socket(name: &str) -> Result<UnixListener, Error> { ... }
    
    /// 发送消息(不等待响应)
    pub fn send_message(stream: &mut UnixStream, msg: &Value) -> Result<(), Error> { ... }
    
    /// 读取消息
    pub fn read_message(stream: &mut UnixStream) -> Result<Value, Error> { ... }
    
    /// 发送消息并读取响应
    pub fn send_and_read(stream: &mut UnixStream, msg: &Value) -> Result<Value, Error> { ... }
}
```

### 第二阶段:连接管理

```rust
/// 连接管理
pub struct Connection {
    main_stream: UnixStream,
    event_stream: UnixStream,
}

impl Connection {
    /// 创建新连接
    pub fn new() -> Result<Self, Error> { ... }
    
    /// 发送消息(不等待响应)
    pub fn send(&mut self, msg: &Value) -> Result<(), Error> { ... }
    
    /// 发送并读取响应
    pub fn send_read(&mut self, msg: &Value) -> Result<Value, Error> { ... }
    
    /// 获取事件流
    pub fn event_stream(&mut self) -> &mut UnixStream { ... }
}
```

### 第三阶段:Activity 管理

```rust
/// Activity 表示一个GUI窗口
pub struct Activity {
    conn: Connection,
    aid: i64,
    dialog: bool,
}

impl Activity {
    /// 创建新 Activity
    pub fn new(dialog: bool) -> Result<Self, Error> { ... }
    
    /// 获取 Activity ID
    pub fn id(&self) -> i64 { ... }
    
    /// 创建 TextView
    pub fn create_text_view(&mut self, text: &str, parent: Option<i64>) -> Result<TextView, Error> { ... }
    
    /// 创建 Button
    pub fn create_button(&mut self, text: &str, parent: Option<i64>) -> Result<Button, Error> { ... }
    
    // 其他组件创建方法...
}
```

### 第四阶段:组件封装

```rust
/// 组件基类
pub struct View {
    activity: *mut Activity,  // 或使用 Rc<RefCell<Activity>>
    id: i64,
}

impl View {
    pub fn id(&self) -> i64 { self.id }
    
    pub fn set_width(&mut self, width: i32) -> Result<(), Error> { ... }
    
    pub fn set_height(&mut self, height: i32) -> Result<(), Error> { ... }
    
    pub fn set_margin(&mut self, margin: i32) -> Result<(), Error> { ... }
}

/// TextView 组件
pub struct TextView {
    view: View,
}

impl TextView {
    pub fn new(activity: &mut Activity, text: &str, parent: Option<i64>) -> Result<Self, Error> { ... }
    
    pub fn set_text(&mut self, text: &str) -> Result<(), Error> { ... }
    
    pub fn set_text_size(&mut self, size: i32) -> Result<(), Error> { ... }
    
    pub fn set_text_color(&mut self, color: i32) -> Result<(), Error> { ... }
}

/// Button 组件
pub struct Button {
    view: View,
}

impl Button {
    pub fn new(activity: &mut Activity, text: &str, parent: Option<i64>) -> Result<Self, Error> { ... }
    
    pub fn set_text(&mut self, text: &str) -> Result<(), Error> { ... }
}

// 其他组件...
```

---

## 🏗️ 库结构设计

### 推荐的目录结构

```
termux-gui-rust-demo/
├── Cargo.toml
├── src/
│   ├── lib.rs                    # 库入口,导出所有公共API
│   ├── connection.rs             # 底层连接管理
│   ├── activity.rs               # Activity 管理
│   ├── view.rs                   # View 基类
│   ├── components/               # 各种UI组件
│   │   ├── mod.rs
│   │   ├── text_view.rs
│   │   ├── button.rs
│   │   ├── edit_text.rs
│   │   ├── checkbox.rs
│   │   ├── switch.rs
│   │   ├── radio.rs
│   │   ├── spinner.rs
│   │   └── layout.rs
│   ├── events.rs                 # 事件处理
│   ├── error.rs                  # 错误类型定义
│   └── constants.rs              # 常量定义
├── examples/                     # 示例程序(重构后更简洁)
│   ├── hello.rs                  # 重命名 main.rs
│   ├── button_demo.rs
│   ├── checkbox_demo.rs
│   ├── input_demo.rs
│   ├── radio_demo.rs
│   ├── spinner_demo.rs
│   └── switch_demo.rs
└── tests/                        # 单元测试
    └── integration_tests.rs
```

### src/lib.rs 架构

```rust
//! # Termux GUI Rust Bindings
//! 
//! 这个库提供了 Termux:GUI 的 Rust 绑定,允许在 Termux 环境中
//! 使用 Rust 创建原生 Android GUI 应用。
//!
//! ## 快速开始
//!
//! ```rust,no_run
//! use termux_gui::{Activity, Button, TextView};
//!
//! fn main() -> Result<(), Box<dyn std::error::Error>> {
//!     // 创建 Activity(对话框模式)
//!     let mut activity = Activity::new(true)?;
//!     
//!     // 创建主布局
//!     let layout = activity.create_linear_layout(None)?;
//!     
//!     // 添加标题
//!     let mut title = activity.create_text_view("Hello Termux!", Some(layout.id()))?;
//!     title.set_text_size(24)?;
//!     
//!     // 添加按钮
//!     let button = activity.create_button("点击我", Some(layout.id()))?;
//!     
//!     // 事件循环
//!     activity.event_loop(|event| {
//!         // 处理事件
//!         Ok(())
//!     })?;
//!     
//!     Ok(())
//! }
//! ```

// 公共导出
pub mod connection;
pub mod activity;
pub mod view;
pub mod components;
pub mod events;
pub mod error;
pub mod constants;

// 便捷导出
pub use connection::Connection;
pub use activity::Activity;
pub use view::View;
pub use events::{Event, EventType};
pub use error::{GuiError, Result};

// 导出所有组件
pub use components::{
    TextView, Button, EditText, Checkbox, Switch,
    RadioButton, RadioGroup, Spinner,
    LinearLayout, NestedScrollView,
};

// 常量
pub use constants::*;
```

---

## 🔄 重构步骤

### 阶段 1: 创建基础库(不影响现有代码)

**时间估计:** 2-3 小时

1. 创建 `src/lib.rs` 和基础模块文件
2.`button_demo.rs` 复制核心函数到对应模块
3. 编译确保库可以构建:`cargo build --lib`
4. **不修改任何示例文件**

**可交付成果:**
- `src/lib.rs` - 库入口
-`src/connection.rs` - 通信函数
- ✅ 编译通过

### 阶段 2: 重构一个示例验证 API

**时间估计:** 1-2 小时

1. 选择最简单的示例(如 `button_demo.rs`2. 创建新文件 `examples/button_demo_v2.rs`
3. 使用新库 API 重写
4. 测试确保功能一致
5. **保留原始文件作为备份**

**可交付成果:**
- ✅ 新示例使用库 API
- ✅ 功能验证通过
- ✅ 代码行数减少 50%+

### 阶段 3: Activity 和 View 封装

**时间估计:** 3-4 小时

1. 实现 `Activity` 结构
2. 实现 `View` 基类
3. 实现 `TextView` 组件
4. 实现 `Button` 组件
5. 更新 `button_demo_v2.rs` 使用高层 API
6. 测试验证

**可交付成果:**
- ✅ Activity 管理器
- ✅ View 基类
- ✅ 2个组件封装
- ✅ 更简洁的示例代码

### 阶段 4: 完善所有组件

**时间估计:** 4-6 小时

1. 实现 `EditText`
2. 实现 `Checkbox`
3. 实现 `Switch`
4. 实现 `RadioButton``RadioGroup`
5. 实现 `Spinner`(修复级联问题)
6. 实现布局组件
7. 为每个组件创建 `_v2` 示例

**可交付成果:**
- ✅ 所有组件封装完成
- ✅ 所有新示例通过测试

### 阶段 5: 迁移所有示例

**时间估计:** 2-3 小时

1. 确认所有 `_v2` 示例工作正常
2. 删除测试文件(test_spinner_*.rs)
3.`_v2` 版本替换原始示例
4. 更新文档

**可交付成果:**
- ✅ 所有示例使用新库
- ✅ 删除重复代码
- ✅ 更新文档

### 阶段 6: 文档和测试

**时间估计:** 2-3 小时

1. 编写 API 文档
2. 添加示例到文档
3. 创建集成测试
4. 更新 README

**可交付成果:**
- ✅ 完整 API 文档
- ✅ 集成测试
- ✅ 更新的 README

---

## 🛡️ 兼容性保证

### 原则

1. **渐进式重构** - 新旧代码并存
2. **充分测试** - 每个阶段都测试
3. **保留备份** - Git 可随时回滚
4. **先加后减** - 先添加新代码,验证后再删除旧代码

### 风险控制

| 风险 | 影响 | 缓解措施 |
|------|------|----------|
| API 设计不当 || 先实现一个示例验证 |
| 破坏现有功能 || 保留原始文件,创建 _v2 版本 |
| 性能下降 || 基准测试对比 |
| 编译错误 || 每个阶段都编译测试 |
| Spinner 问题 || 专门处理,单独测试 |

---

## 🧪 测试计划

### 测试检查清单

**阶段 1 测试:**
- [ ] `cargo build --lib` 成功
- [ ] `cargo doc --lib` 成功
- [ ] 没有编译警告

**阶段 2 测试:**
- [ ] `button_demo_v2` 可以编译
- [ ] 界面显示正常
- [ ] 按钮点击计数正常
- [ ] 退出事件正常

**阶段 3 测试:**
- [ ] Activity 创建成功
- [ ] TextView 显示正常
- [ ] Button 点击正常
- [ ] 代码量减少 > 50%

**阶段 4 测试:**
- [ ] EditText 输入正常
- [ ] Checkbox 状态切换正常
- [ ] Switch 切换正常
- [ ] RadioButton 单选正常
- [ ] Spinner 显示和选择正常(重点测试)
- [ ] 布局正常

**阶段 5 测试:**
- [ ] 所有示例编译通过
- [ ] 所有示例运行正常
- [ ] 没有功能退化

**最终验证:**
- [ ] 编译无警告:`cargo build --all --release`
- [ ] 所有示例测试通过
- [ ] 文档生成:`cargo doc --open`
- [ ] README 指令可用

---

## 📈 预期收益

### 代码质量

- **代码减少:** 480-600 行重复代码 → 0
- **示例简化:** 每个示例减少 40-50 行样板代码
- **可维护性:** 修改一处影响全部
- **可扩展性:** 添加组件更容易

### 开发效率

- **新示例创建时间:** 从 30 分钟 → 10 分钟
- **新组件添加时间:** 从 2 小时 → 1 小时
- **Bug 修复范围:** 从 12 个文件 → 1 个文件

### 用户体验

- **学习曲线:** 更平缓,API 更清晰
- **示例清晰度:** 专注于功能,不是底层细节
- **文档质量:** 统一的 API 文档

---

## 📋 Cargo.toml 更新

```toml
[package]
name = "termux-gui"  # 改为更通用的名称
version = "0.2.0"     # 重构版本
edition = "2021"
authors = ["Your Name <your@email.com>"]
description = "Rust bindings for Termux:GUI - Build Android GUI apps in Rust"
license = "MIT"
repository = "https://github.com/andelf/termux-gui-rust-demo"
keywords = ["termux", "android", "gui", "ui"]
categories = ["api-bindings", "gui"]

[lib]
name = "termux_gui"
path = "src/lib.rs"

[[bin]]
name = "termux-gui-demo"
path = "src/main.rs"

[dependencies]
serde_json = "1.0"
rand = "0.8"
libc = "0.2"

[dev-dependencies]
# 用于测试

[profile.release]
opt-level = 3
lto = true

[[example]]
name = "hello"
path = "examples/hello.rs"

[[example]]
name = "button"
path = "examples/button_demo.rs"

# ... 其他示例
```

---

## ✅ 决策点

在开始重构前,需要确认:

### 1. 库名称
- [ ] `termux-gui` (推荐,与 Python 库一致)
- [ ] `termux-gui-rust` 
- [ ] `termux_gui` (当前)

### 2. API 风格
- [ ] 面向对象风格(推荐)- `activity.create_button()`
- [ ] 函数式风格 - `create_button(&activity)`
- [ ] 混合风格

### 3. 错误处理
- [ ] 自定义 Error 类型(推荐)
- [ ] 使用 `std::io::Error`
- [ ] 使用 `anyhow`

### 4. 所有权模型
- [ ] `Rc<RefCell<>>` 共享所有权
- [ ] 生命周期引用(推荐,零成本)
- [ ] `Arc<Mutex<>>` 线程安全

### 5. 重构范围
- [ ] 完全重构(推荐)
- [ ] 仅提取公共函数
- [ ] 分阶段,先验证

---

## 🚀 开始重构

### 准备工作

```bash
# 1. 创建新分支
git checkout -b refactor/extract-lib

# 2. 备份当前状态
git tag backup-before-refactor

# 3. 确认所有测试通过
cargo build --examples --release
./test_all.sh  # 如果有测试脚本

# 4. 创建基础目录结构
mkdir -p src/components
touch src/lib.rs src/connection.rs src/activity.rs src/view.rs
touch src/components/mod.rs
```

### 第一个 PR

**标题:** `🔧 Phase 1: Extract core communication functions to lib.rs`

**变更:**
- 添加 `src/lib.rs``src/connection.rs`
- 导出核心通信函数
- 不修改任何示例文件
- 更新 `Cargo.toml` 添加 `[lib]` section

**测试:**
- `cargo build --lib` 通过
- `cargo test --lib` 通过(如果有测试)
- `cargo build --examples` 仍然通过

---

## 📝 总结

### 当前问题
1. ✅ 480-600 行重复代码
2. ✅ 示例文件过于复杂
3. ✅ 维护困难
4. ⚠️ Spinner 级联更新问题
5. ✅ 缺少统一 API

### 解决方案
1. 📦 提取公共代码到 `lib.rs`
2. 🏗️ 创建高层 API(Activity, View, Components)
3. 🔄 渐进式重构,保证兼容性
4. 🐛 在重构过程中修复 Spinner 问题
5. 📚 改进文档和示例

### 预期结果
- ✨ 代码量减少 40%+
- 🎯 API 清晰易用
- 🚀 开发效率提升 3倍
- 📖 示例更易理解
- 🔧 易于维护和扩展

### 时间估计
- **总计:** 14-21 小时
- **最小可用版本(阶段 1-3):** 6-9 小时
- **完整版本(阶段 1-6):** 14-21 小时

### 建议
**立即开始阶段 1**,创建基础库但不破坏现有代码。这样可以:
1. 验证架构设计
2. 不影响现有功能
3. 随时可以回滚
4. 为后续工作打基础

---

**准备好开始重构了吗?** 🚀

我建议从**阶段 1**开始,只提取核心函数,完全不修改示例文件,这样风险最小。