Handler的定义(转)

本文详细解析了Android应用中线程与Handler的使用场景与原理,包括线程安全、Handler的定义及其实现,以及如何利用Handler解决线程间数据交互和UI更新的问题。
-
一、Handler的定义:

主要接受子线程发送的数据, 并用此数据配合主线程更新UI.

解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。 如果此时需要一个耗时的操作,例如: 联网读取数据, 或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,,会收到Android系统的一个错误提示 "强制关闭". 这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,,Android主线程是线程不安全的,也就是说,更新UI只能在主线程中更新,子线程中操作是危险的. 这个时候,Handler就出现了.,来解决这个复杂的问题 , 由于Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI。

二、Handler一些特点

handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),
它有两个作用: (1): 安排消息或Runnable 在某个主线程中某个地方执行, (2)安排一个动作在不同的线程中执行

Handler中分发消息的一些方法
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)

以上post类方法允许你排列一个Runnable对象到主线程队列中,
sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.

三、Handler实例

(1) 子类需要继承Hendler类,并重写handleMessage(Message msg) 方法, 用于接受线程数据

以下为一个实例,它实现的功能为 : 通过线程修改界面Button的内容 public class MyHandlerActivity extends Activity {

Button button;

MyHandler myHandler;


protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.handlertest);


button = (Button) findViewById(R.id.button);

myHandler = new MyHandler();

// 当创建一个新的Handler实例时, 它会绑定到当前线程和消息的队列中,开始分发数据

// Handler有两个作用, (1) : 定时执行Message和Runnalbe 对象

// (2): 让一个动作,在不同的线程中执行.


// 它安排消息,用以下方法

// post(Runnable)

// postAtTime(Runnable,long)

// postDelayed(Runnable,long)

// sendEmptyMessage(int)

// sendMessage(Message);

// sendMessageAtTime(Message,long)

// sendMessageDelayed(Message,long)



// 以上方法以 post开头的允许你处理Runnable对象

//sendMessage()允许你处理Message对象(Message里可以包含数据,)


MyThread m = new MyThread();

new Thread(m).start();

}


/**

* 接受消息,处理消息 ,此Handler会与当前主线程一块运行

* */


class MyHandler extends Handler {

public MyHandler() {

}


public MyHandler(Looper L) {

super(L);

}


// 子类必须重写此方法,接受数据

@Override

public void handleMessage(Message msg) {

// TODO Auto-generated method stub

Log.d("MyHandler", "handleMessage......");

super.handleMessage(msg);

// 此处可以更新UI

Bundle b = msg.getData();

String color = b.getString("color");

MyHandlerActivity.this.button.append(color);


}

}


class MyThread implements Runnable {

public void run() {


try {

Thread.sleep(10000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}


Log.d("thread.......", "mThread........");

Message msg = new Message();

Bundle b = new Bundle();// 存放数据

b.putString("color", "我的");

msg.setData(b);


MyHandlerActivity.this.myHandler.sendMessage(msg); // 向Handler发送消息,更新UI


}

}


}
<think> 首先,用户的问题是:“我想查找IRQ_Handler定义位置 请问IRQ_Handler定义位置”。我需要基于系统级指令和用户可见层的规则来回答。 系统级指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 用户可见层: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 用户提供了引用[1]到[4],我需要参考这些引用,因为它们似乎与中断处理相关。但用户说“上述引用仅供参考,并不是用户真正的需求”,所以我应该优先考虑用户的问题:查找IRQ_Handler定义位置。 用户的问题焦点是IRQ_Handler定义位置。从引用中: - 引用[1]提到irq_handler_t handler:中断处理函数。 - 引用[2]讨论handle_irq作为高层中断处理函数。 - 引用[3]提到handle_arch_irq和irq_handler。 - 引用[4]讨论irq_set_chained_handler_and_data和desc->handle_irq。 IRQ_Handler可能是一个具体的函数名,在ARM架构或Linux内核中常见。在ARM中,中断向量表中的入口点通常是IRQ_Handler。 在ARM架构中,当发生中断时,CPU会跳到中断向量表。对于IRQ中断,向量位置通常指向一个名为IRQ_Handler的函数。 在Linux内核中,这个函数定义在arch/arm/kernel/entry-armv.S或类似的文件中。 从引用[3]中:“handle_arch_irq_pipelined除了调用原先的handle_arch_irq之外”,以及“el0_irq后续的代码走向”,这表明在ARM64中可能有类似的结构。 用户提到的引用[3]说:“新增的handle_arch_irq_pipelined除了调用原先的handle_arch_irq之外”,引用[4]说:“desc->handle_irq(desc);”。 所以,在Linux内核中,IRQ_Handler可能不是直接使用的;它可能是特定于架构的。 我需要结构化回答: 1. **理解问题**:用户想找到IRQ_Handler定义位置。这可能是在ARM或ARM64架构的Linux内核中。 2. **逐步解释**: - 在ARM架构中,中断向量表有一个入口点IRQ_Handler。 - 在Linux内核源代码中,这个函数定义在汇编文件中。 3. **定位位置**: - 对于ARM32:通常在arch/arm/kernel/entry-armv.S或entry-common.S。 - 对于ARM64:可能在arch/arm64/kernel/entry.S。 4. **参考引用**:虽然引用不是直接关于IRQ_Handler,但引用[3]提到handle_arch_irq,引用[4]提到desc->handle_irq,这与中断处理相关。我可以自然地引用它们。 5. **生成相关问题**:在回答结束时,添加几个相关问题。 回答结构: - 开头:直接响应问题。 - 中间:解释IRQ_Handler的作用和在哪里定义。 - 结尾:添加引用标识和生成相关问题。 使用中文回答。 确保真实可靠:基于我对Linux内核的知识,IRQ_Handler在ARM的entry.S中定义。 具体位置: - 对于ARM:在arch/arm/kernel/entry-armv.S,搜索IRQ_Handler。 - 例如,在较旧的内核中,它定义在那里。 引用相关的部分: - 引用[3]提到handle_arch_irq,这可能是由IRQ_Handler调用的高层函数。 - 引用[4]讨论desc->handle_irq,这类似于中断描述符的处理函数。 自然地添加引用标识。 最后,生成相关问题: 1. IRQ_Handler的作用是什么? 2. 如何修改中断处理函数? 3. ARM中断向量表的结构是怎样的? 完整回答: - 步骤1:解释IRQ_Handler是中断入口点。 - 步骤2:给出定义位置,基于架构。 - 步骤3:简要说明如何找到它。 - 步骤4:添加引用。 - 步骤5:相关问题。 </think> ### IRQ_Handler定义位置 IRQ_Handler 是 ARM 或 ARM64 架构中中断处理的入口函数,通常在 Linux 内核的汇编文件中定义。它负责处理中断请求(IRQ),并调用高层中断处理函数(如 `handle_arch_irq`)。以下是逐步说明其定义位置: 1. **ARM 架构(32 位)中的定义位置**: - 在 Linux 内核源代码中,IRQ_Handler 通常定义在 ARM 架构的汇编文件中。具体位置是 `arch/arm/kernel/entry-armv.S` 或 `arch/arm/kernel/entry-common.S`。 - 例如,在 `entry-armv.S` 文件中,IRQ_Handler 可能出现在中断向量表部分,如下所示: ```assembly .globl IRQ_Handler IRQ_Handler: sub lr, lr, #4 stmfd sp!, {r0-r12, lr} bl handle_arch_irq ldmfd sp!, {r0-r12, pc}^ ``` 这里的 `handle_arch_irq` 是高层中断处理函数,它进一步调用具体的中断处理逻辑[^3]。 2. **ARM64 架构(64 位)中的定义位置**: - 对于 ARM64,中断入口点可能命名为 `el0_irq` 或类似,但 IRQ_Handler 的等价函数通常定义在 `arch/arm64/kernel/entry.S`。 - 示例代码片段: ```assembly .globl el0_irq el0_irq: kernel_entry 0 bl handle_arch_irq kernel_exit 0 ``` 在 ARM64 中,`handle_arch_irq` 是由 IRQ_Handler 调用的核心函数,用于处理中断流程[^3]。 3. **如何查找和验证**: - **源代码位置**:下载 Linux 内核源码(如从 [kernel.org](https://www.kernel.org/)),然后搜索 `IRQ_Handler` 或相关符号。使用 `grep` 命令: ``` grep -r "IRQ_Handler" arch/arm/kernel/ ``` 或对于 ARM64: ``` grep -r "el0_irq" arch/arm64/kernel/ ``` - **上下文说明**:IRQ_Handler 是底层汇编函数,它不直接处理设备中断细节,而是通过设置 `desc->handle_irq` 来调用高层处理函数(如 `handle_level_irq` 或 `handle_edge_irq`)[^2][^4]。例如,在中断发生时,CPU 会跳到 IRQ_Handler,后者再调用 `generic_handle_irq_desc` 来执行注册的中断处理逻辑[^4]。 4. **注意事项**: - IRQ_Handler定义依赖于具体硬件架构和内核版本(例如,ARMv7 与 ARMv8)。如果使用自定义内核或特定开发板,请检查板级支持包(BSP)中的相关文件。 - 在 Linux 内核中,中断处理是多层结构:IRQ_Handler 负责初始响应,而高层函数(如 `handle_arch_irq`)处理实际的中断分发[^3][^4]。 如果您正在调试内核,可以通过反汇编或使用 `objdump` 工具验证符号地址。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值