feat: 大幅增强原生行为 — 修复P0 Bug + 补全核心API

P0 Bug 修复:
- Canvas.drawBitmap 重复定义导致重载丢失 → 合并为*args重载
- String.hashCode() 不可达的第二return → 修复为单return
- File.compareTo() 调用不存在的__cmp__ → 改为显式比较
- HashMap.remove() 逻辑错误 → 区分单参(返回旧值)/双参(返回boolean)

P1 核心行为增强:
- Handler: sendMessage/sendMessageDelayed 现在真正入队异步执行
- Looper: loop() 实现真正的消息循环(按when时间取出到期消息)
- AsyncTask: execute() 在后台线程池执行,完成后主线程回调
- Bundle: 新增12个数组类型put/get方法
- Math.round: 改为Java语义(floor(a+0.5))而非Python银行家舍入
- Thread: currentThread()缓存对象, 新增join/getState/getId/getPriority
- String: 新增strip/repeat/isBlank/lines/subSequence/getChars/chars/formatted/translateEscapes

P2 缺失API补全:
- 新增21个Java标准Exception类 (NullPointerException等)
- View: 新增39个事件处理/监听器/位置尺寸方法
- Activity: 新增33个生命周期/权限/UI方法
- Context: 新增22个文件流/权限/资源/主题方法
- Canvas: 支持 Canvas(Bitmap) 构造函数重载
- __init__.py: __all__ 补全Exception体系和Activity类
This commit is contained in:
shuiyu1123 committed 2026-06-24 15:04:17 +00:00
1 parent 4645015004
commit 8c3bd3c415
9 files changed
+1017 -52

No files matched your search

+214 -15
View File
@@ -466,6 +466,61 @@ class Bundle(BaseBundle):
def putIntegerArrayList(self, key: str, value: Optional[List[int]]):
self._map[key] = value
# ---- 数组类型 ----
def putIntArray(self, key: str, value: Optional[List[int]]):
self._map[key] = list(value) if value is not None else None
def getIntArray(self, key: str) -> Optional[List[int]]:
v = self._map.get(key)
if isinstance(v, list):
return [int(x) for x in v]
return None
def putStringArray(self, key: str, value: Optional[List[str]]):
self._map[key] = list(value) if value is not None else None
def getStringArray(self, key: str) -> Optional[List[str]]:
v = self._map.get(key)
if isinstance(v, list):
return [str(x) for x in v]
return None
def putLongArray(self, key: str, value: Optional[List[int]]):
self._map[key] = list(value) if value is not None else None
def getLongArray(self, key: str) -> Optional[List[int]]:
v = self._map.get(key)
if isinstance(v, list):
return [int(x) for x in v]
return None
def putBooleanArray(self, key: str, value: Optional[List[bool]]):
self._map[key] = list(value) if value is not None else None
def getBooleanArray(self, key: str) -> Optional[List[bool]]:
v = self._map.get(key)
if isinstance(v, list):
return [bool(x) for x in v]
return None
def putDoubleArray(self, key: str, value: Optional[List[float]]):
self._map[key] = list(value) if value is not None else None
def getDoubleArray(self, key: str) -> Optional[List[float]]:
v = self._map.get(key)
if isinstance(v, list):
return [float(x) for x in v]
return None
def putByteArray(self, key: str, value: Optional[List[int]]):
self._map[key] = list(value) if value is not None else None
def getByteArray(self, key: str) -> Optional[List[int]]:
v = self._map.get(key)
if isinstance(v, list):
return [int(x) & 0xFF for x in v]
return None
def putAll(self, bundle: "Bundle"):
if bundle:
self._map.update(bundle._map)
@@ -729,6 +784,14 @@ class Message(Stub):
def setTarget(self, handler: "Handler"):
self._target = handler
@property
def target(self) -> Optional["Handler"]:
return self._target
@target.setter
def target(self, handler: "Handler"):
self._target = handler
def getCallback(self) -> Optional[Callable]:
return self._callback
@@ -769,15 +832,17 @@ class Looper(Stub):
_main_looper: Optional["Looper"] = None
_thread_local = threading.local()
def __init__(self):
def __init__(self, quit_allowed: bool = True):
super().__init__()
self._thread = threading.current_thread()
self._running = False
self._message_queue: List[Message] = []
self._quit_allowed = True
self._queue_lock = threading.Lock()
self._quit_allowed = quit_allowed
@staticmethod
def prepare():
"""为当前线程准备一个 Looper"""
looper = Looper()
Looper._thread_local.looper = looper
return looper
@@ -799,16 +864,76 @@ class Looper(Stub):
@staticmethod
def loop():
"""运行消息循环,处理到期的消息"""
looper = Looper.myLooper()
if looper is None:
raise RuntimeError("No Looper prepared")
looper._running = True
while looper._running:
msg = looper._next()
if msg is not None:
target = msg._target
if target is not None:
target.dispatchMessage(msg)
msg.recycle()
else:
# 无到期消息,短暂 sleep 避免忙等
_time.sleep(0.001)
def _next(self) -> Optional[Message]:
"""非阻塞地取出一条到期消息(when <= now)"""
with self._queue_lock:
now = SystemClock.uptimeMillis()
for i, msg in enumerate(self._message_queue):
if msg.when <= now:
return self._message_queue.pop(i)
return None
def _enqueue(self, msg: Message):
"""将消息按 when 时间顺序入队"""
with self._queue_lock:
inserted = False
for i, m in enumerate(self._message_queue):
if msg.when < m.when:
self._message_queue.insert(i, msg)
inserted = True
break
if not inserted:
self._message_queue.append(msg)
def _remove_callbacks(self, callback):
"""从队列中移除匹配 callback 的消息"""
with self._queue_lock:
self._message_queue = [
m for m in self._message_queue
if m._callback is not callback
]
def _remove_messages(self, what: int):
"""从队列中移除匹配 what 的消息"""
with self._queue_lock:
self._message_queue = [
m for m in self._message_queue
if m.what != what
]
def _has_messages(self, what: int) -> bool:
"""检查队列中是否有匹配 what 的消息"""
with self._queue_lock:
return any(m.what == what for m in self._message_queue)
def quit(self):
self._running = False
"""退出消息循环"""
if not self._quit_allowed:
raise RuntimeError("Main Looper is not allowed to quit")
with self._queue_lock:
self._running = False
self._message_queue.clear()
def quitSafely(self):
self._running = False
"""安全退出,仅停止循环(已入队消息不再处理)"""
with self._queue_lock:
self._running = False
def isCurrentThread(self) -> bool:
return threading.current_thread() == self._thread
@@ -858,7 +983,6 @@ class Handler(Stub):
def postDelayed(self, r: Callable, delay_ms: int) -> bool:
msg = Message.obtain(self)
msg._callback = r
msg.when = int(_time.time() * 1000) + delay_ms
return self.sendMessageDelayed(msg, delay_ms)
def postAtTime(self, r: Callable, uptime_ms: int) -> bool:
@@ -869,6 +993,11 @@ class Handler(Stub):
def sendMessage(self, msg: Message) -> bool:
msg._target = self
looper = self._looper
if looper is not None and looper._running:
looper._enqueue(msg)
return True
# 当前线程无运行中的 Looper,回退到同步执行(保持兼容性)
self.dispatchMessage(msg)
return True
@@ -878,31 +1007,53 @@ class Handler(Stub):
def sendMessageDelayed(self, msg: Message, delay_ms: int) -> bool:
msg._target = self
msg.when = int(_time.time() * 1000) + delay_ms
msg.when = SystemClock.uptimeMillis() + delay_ms
looper = self._looper
if looper is not None and looper._running:
looper._enqueue(msg)
return True
# 回退到同步执行
self.dispatchMessage(msg)
return True
def sendMessageAtTime(self, msg: Message, uptime_ms: int) -> bool:
msg._target = self
msg.when = uptime_ms
looper = self._looper
if looper is not None and looper._running:
looper._enqueue(msg)
return True
self.dispatchMessage(msg)
return True
def sendMessageAtFrontOfQueue(self, msg: Message) -> bool:
msg._target = self
msg.when = 0
looper = self._looper
if looper is not None and looper._running:
with looper._queue_lock:
looper._message_queue.insert(0, msg)
return True
self.dispatchMessage(msg)
return True
def removeCallbacks(self, r: Callable):
pass
looper = self._looper
if looper is not None:
looper._remove_callbacks(r)
def removeMessages(self, what: int):
pass
looper = self._looper
if looper is not None:
looper._remove_messages(what)
def obtainMessage(self, what: int = 0) -> Message:
return Message.obtain(self, what)
def hasMessages(self, what: int) -> bool:
looper = self._looper
if looper is not None:
return looper._has_messages(what)
return False
def getLooper(self) -> Looper:
@@ -950,6 +1101,42 @@ class HandlerThread(threading.Thread, Stub):
return self.quit()
# ═══════════════════════════════════════════════════════════════
# AsyncTask Executor (守护线程池)
# ═══════════════════════════════════════════════════════════════
class _AsyncTaskExecutor:
"""守护线程池执行器 — 用于 AsyncTask 后台执行,不阻塞程序退出。
使用 BoundedSemaphore 限制并发数,每个任务在独立的守护线程中运行。
"""
def __init__(self, max_workers: int = 4):
self._max_workers = max_workers
self._semaphore = threading.BoundedSemaphore(max_workers)
self._shutdown_flag = False
def submit(self, fn, *args, **kwargs):
if self._shutdown_flag:
raise RuntimeError("Executor has been shut down")
self._semaphore.acquire()
def _run():
try:
fn(*args, **kwargs)
finally:
self._semaphore.release()
t = threading.Thread(target=_run, daemon=True)
t.start()
def execute(self, command):
self.submit(command)
def shutdown(self, wait: bool = True):
self._shutdown_flag = True
# ═══════════════════════════════════════════════════════════════
# AsyncTask
# ═══════════════════════════════════════════════════════════════
@@ -967,6 +1154,7 @@ class AsyncTask(Stub):
self._status = AsyncTask.Status.PENDING
self._result: Any = None
self._cancelled = False
self._handler = Handler(Looper.getMainLooper())
def doInBackground(self, *params) -> Any:
raise NotImplementedError
@@ -984,19 +1172,25 @@ class AsyncTask(Stub):
pass
def execute(self, *params) -> "AsyncTask":
return self.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, *params)
def executeOnExecutor(self, exec: Any, *params) -> "AsyncTask":
self._status = AsyncTask.Status.RUNNING
self.onPreExecute()
exec.submit(self._run_background, params)
return self
def _run_background(self, params):
"""在后台线程中执行 doInBackground,完成后通过 Handler 回调主线程"""
try:
self._result = self.doInBackground(*params)
except Exception as e:
self._result = e
self._status = AsyncTask.Status.FINISHED
if not self._cancelled:
self.onPostExecute(self._result)
return self
def executeOnExecutor(self, exec: Any, *params) -> "AsyncTask":
return self.execute(*params)
if self._cancelled:
self._handler.post(lambda: self.onCancelled(self._result))
else:
self._handler.post(lambda: self.onPostExecute(self._result))
def get(self) -> Any:
return self._result
@@ -1012,7 +1206,12 @@ class AsyncTask(Stub):
return True
def publishProgress(self, *values):
self.onProgressUpdate(*values)
self._handler.post(lambda: self.onProgressUpdate(*values))
# 初始化默认执行器
AsyncTask.THREAD_POOL_EXECUTOR = _AsyncTaskExecutor(max_workers=4)
AsyncTask.SERIAL_EXECUTOR = _AsyncTaskExecutor(max_workers=1)
# ═══════════════════════════════════════════════════════════════