Android中的Handler消息处理机制

Android进阶系列9-Android异步消息处理Handler机制解析 Android 异步消息处理机制 ,从源码带你理解 Looper、Handler、Message、MessageQueue四者关系,以及使用的一些注意点! 阅读详情

在几天在学习中用到了android中的Handler消息处理机制,但是对它的原理不太清楚,自己一边学习一边看源代码整理了下Handler的消息处理机制。

首先根据官方给的例子来说明调用关系,在一个线程中创建Handler对象:

  *  class LooperThread extends Thread {
  *      public Handler mHandler;
  *
  *      public void run() {
  *          Looper.prepare();
  *
  *          mHandler = new Handler() {
  *              public void handleMessage(Message msg) {
  *                  // process incoming messages here
  *              }
  *          };
  *
  *          Looper.loop();
  *      }
  *  }
1、可以看到首先会调用 Looper.prepare(); 方法,然后在创建Handler对象,那么这个Looper又是什么呢,这个要到源码中去看了。

public class Looper {
    private static final String TAG = "Looper";

    // sThreadLocal.get() will return null unless you've called prepare().
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    private static Looper sMainLooper;  // guarded by Looper.class

    final MessageQueue mQueue;
    final Thread mThread;
    volatile boolean mRun;

    private Printer mLogging;

     /** Initialize the current thread as a looper.
      * This gives you a chance to create handlers that then reference
      * this looper, before actually starting the loop. Be sure to call
      * {@link #loop()} after calling this method, and end it by calling
      * {@link #quit()}.
      */
    public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

可以清楚的看到在Looper的prepare()方法中先是 new 了一个Looper对象,Looper的构造方法在这

    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mRun = true;
        mThread = Thread.currentThread();
    }

然后sThreadLocal.set()把这个new 出来的 Looper对象放入到 ThreadLocal中,这就是整个Looper.prepare()方法做的事情

2、在例子中 new 了一个Handler对象,那么就从源码中找出这个Handler对象是怎么new出来的

    public Handler(Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

在代码中new的时候先调用的Handler的默认构造方法,然后在这个默认构造方法中调用了上面带两个参数的构造方法,在这个方法中,mLooper = Looper.myLooper()方法很重要,

去代码中找到这个方法:

    /**
     * Return the Looper object associated with the current thread.  Returns
     * null if the calling thread is not associated with a Looper.
     */
    public static Looper myLooper() {
        return sThreadLocal.get();
    }

清楚的看出通过sThreadLocal的get()方法得到了之前Looper.prepare()方法放入的Looper对象,所以Handler对象中的Looper对象,就是之前线程中的Looper对象。

接着上面的代码, mQueue = mLooper.mQueue; 这行代码得到Looper对象中的MessageQueue对象,那么这个MessageQueue对象又是什么时候创建的呢,往前看,发现是在Looper的prepare()方法中创建Looper对象的时候就创建了,所以也就是说 一个Looper对象对应着一个MessageQueue对象,而一个线程中只有一个Looper对象。


3、经过上面,Handler对象就创建完毕了,然后 调用Looper.loop()方法,这个loop()方法又是干嘛的呢,再去代码里寻找

    /**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;

        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

            msg.target.dispatchMessage(msg);

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }

            msg.recycle();
        }
    }

可以看到首先得到MessageQueue对象,然后是一个for死循环,在这个循环中,先是 Message msg = queue.next(); 这行代码意思是什么?

这个next方法其实就是把MessageQueue队列中的Message方法拿出来,然后msg.target.dispatchMessage(msg); msg.target就是代表了这个Message对象在哪个Handler中,然后调用dispatchMessage()方法,在这个方法中

    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

可以看到是调用了hanleMessage(msg)方法,这个就是我们在之前 创建Handler对象时重写的那个handlerMessage方法,然后我们就得到了发送出来的Message对象,自己去处理消息了。


4、以上是一个线程中Handler创建过程和接收到Message过程,那么发送消息的过程呢,我们知道Handler最多用于在不同线程中,往另一个线程里发送消息,然后在那个线程中接收到handler发送到的消息,对消息进行处理。那么发送过程是怎么实现的

    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

上面是sendMessage时候调用的一系列方法,看倒数第二个方法,可以看看到是先得到MessageQueue对象,然后最后一个方法中,调用queue.enqueueMessage()方法,在这个方法中把Message消息放入到MessageQueue消息队列中,在之前的Looper.loop()方法不断的从消息队列中取出Message对象,然后去处理消息。


经过上面的分析可以很清楚的看到了整个Handler消息机制的原理了,总结下,就是一个线程中有一个Looper对象,这个Looper对象有一个MessageQueue消息队列,别的线程中通过拥有handler对象实例来调用sendMessage()方法,在这个方法中是用的Looper对象的MessageQueue消息队列来把Message放入到队列中,然后在第一个线程中,Looper对象的loop()方法把消息队列中的Message消息取出,然后交给Handler对象的重写的handleMessage()方法来处理得到的消息。


python cartopy绘制扇形区域图/cartopy绘制北极部分区域 实际上,这个问题原因还是由于投影转换的问题,在set_extend时,绘制的上下边界仍然是方形、未被正确投影的边界,与我们的set_boundary存在冲突,最根本的原因还是在于cartopy对于投影计算的一些缺陷。另外我们需要指出的是:**该方法不适用于极地投影,即NorthPolarStereo,由于NorthPolarStereo本身投影特性只需一个参数,本身并不适合。我们绘制极地投影时,同样也是使用set_boundary绘制圆形边界,那么当我们想要绘制扇形时,可以通过。请根据喜好自行选择, 阅读详情

相关推荐

Synopsys PCIe IP 实战笔记:手把手教你配置本地数字回环(PIPE/RMMI)

本文详细介绍了Synopsys PCIe IP本地数字回环(PIPE/RMMI)的配置与调试全流程,涵盖硬件连接、寄存器操作及实战技巧。通过数字回环模式,开发者可在无真实对端设备的情况下验证PCIe接口功能,适用于芯片验证和FPGA原型开发。文章还提供了常见问题排查和性能优化建议,助力高效完成协议解析与调试。

weixin_30394669的博客 323

Android开发——消息机制(二)Handler的使用

Hanlder的使用方法 1. 创建Handler成员变量对象,并重写其handleMessage()方法 2. 在分/主线程创建Message对象 3. 使用handler对象发送Message 4. 主线程,在hanlerMessage()中处理消息 Handler的原理 运行效果图 点击GET Submit1进行普通的同步工作 点击GET Submit2使用Handle...

奔跑的狮子 340

别急着编译!修复银河麒麟OpenSSH漏洞前,先搞懂ssh、sshd版本与apt仓库的“爱恨情仇”

本文深度解析银河麒麟OpenSSH漏洞(CVE-2023-38408)修复策略,揭示版本差异背后的企业级维护逻辑,提供从APT升级到源码编译的多维度方案评估。特别针对路径隔离方案和离线环境处理给出技术细节,帮助企业制定兼顾安全与稳定的升级决策框架。

weixin_26642481的博客 454

Android Handler消息处理机制

消息处理机制本质:一个线程开启循环模式持续监听并依次处理其他线程给它发的消息。简单的说:一个线程开启一个无限循环模式,不断遍历自己的消息列表,如果有消息就挨个拿出来做处理,如果列表没消息,自己就堵塞(相当于wait,让出cpu资源给其他线程),其他线程如果想让该线程做什么事,就往该线程的消息队列插入消息,该线程会不断从队列里拿出消息做处理。

轻口味的专栏 3403

Memory SystemsCache, DRAM, Disk翻译学习DRAM部分(二)

DRAM 的发展史

qq_33473931的博客 995

Windows域账户无管理员权限也能装软件?3步搞定UAC设置(附安全提醒)

本文探讨了在Windows域环境中,如何通过配置用户账户控制(UAC)实现临时提权,让无管理员权限的域账户也能安装软件。文章详细介绍了三步走策略:临时加入本地管理员组、调整UAC行为以及至关重要的权限回收,并提供了脚本化部署方案与安全实践指南,旨在平衡企业IT管理的效率与安全。

fox11的博客 759

安卓Handler消息处理机制详解

消息处理机制可以算得上是每个安卓开发入行最先接触的机制之一。它为我们提供了一种线程间通信方式。本文就讲解Handler提供的各种用法以及其运行机理。

lingchen881218的博客 2315

IAR9.X半主模式异常解析:为何硬件复位后仍陷调试状态?

本文深入解析了IAR 9.X半主模式异常问题,探讨了硬件复位后MCU仍陷调试状态的原因及解决方案。通过分析半主模式工作机制,提供了禁用半主功能、重写低级IO函数等具体方法,并给出了版本兼容性处理和调试与量产配置分离的优化建议,帮助开发者有效解决复位异常问题。

oo7890的博客 605

Android 全面解析 Handler 异步消息处理机制

      Android 是不容许在子线程中进行 UI 操作的,但是有些时候我们必须在子线程里去执行一些耗时任务,然后根据执行的结果来更新相应的 UI 控件,对于这种情况,Android 提供了一套异步消息处理机制,完美解决了在子线程中进行 UI 相关操作的问题,今天我们就来一起学习一下这个 Android 系统提供的异步消息处理机制,下面是我们学习的内容大纲                  ...

QDJdeveloper 1348

​​10.3 时间敏感网络(TSN)协议适配​

本文探讨了时间敏感网络(TSN)协议在PCIe网络加速卡开发中的适配方案,重点分析了时间同步、流量调度和冗余传输三大核心问题。研究从协议实现、硬件加速设计和驱动优化三个维度展开,提出采用FPGA实现PTP时钟同步、动态TAS调度器以及双路径冗余传输等技术方案。通过工业控制网络案例验证,该方案将端到端延迟从120μs降至8μs,带宽利用率提升至92%,同时实现了100%的确定性保障。研究还总结了调试工具和典型问题解决方法,为TSN在PCIe网络中的实际应用提供了技术参考。

amy_mhd的博客 364

《一》:LBE,VR 大空间系列——场景环境需求解析

当前,大量 VR 体验活动在室内场地开展。因此,对于场地照明有特定要求:除天花板外,场地的所有表面均需有照明覆盖。这是为了保证玩家无论处于场地的哪个位置,地面与墙面都不会出现明显的影子。场地内不建议安装射灯或高强度的点光源,若已安装此类灯具,需使用柔光板进行遮盖。此外,要避免在阳光下使用 VR 设备台。参考图(请忽略其中Maker标签)

unitygroup的博客 944

Android之handler消息处理机制详解

介绍android中常见的handler消息处理机制,分析源码

qq_43800449的博客 4189

华为OD机试真题2025双机位C卷 Java&Go 实现【卡牌游戏】

小明正在尝试一种新的牌游戏。游戏规则只如下:首先,小明拿到一张写有数字m的牌。 然后,他会拿到另外n张牌,上面分别写有不同的数字,牌排成一排。小明的目标是从这排牌中找到一串连续的牌,这些牌上数字的总和可以被 m整除。你的任务是判断小明是否可以完成这个目标。

MISAYAONE的博客 393

Android应用程序消息处理机制(Looper、Handler)分析

Android应用程序是通过消息来驱动的,系统为每一个应用程序维护一个消息队例,应用程序的主线程不断地从这个消息队例中获取消息(Looper),然后对这些消息进行处理(Handler),这样就实现了通过消息来驱动应用程序的执行,本文将详细分析Android应用程序的消息处理机制。        前面我们学习Android应用程序中的Activity启动(Android应用程序启动过程源代码分析和A

老罗的Android之旅 11万+

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Android异步消息处理机制之Handler

一 在Android中异步消息处理机制有Handler以及AsyncTask两种方式,而AsyncTask也是Handler的封装,今天就学习一下Handler机制。 二 与Handler消息机制相关的类主要有以下四个: Handler Message MessageQueue Looper 三 Handler主要用于发送消息,以及处理消息。发送消息的方法主要是post和send两种。 post方法有: public final boolean post(Runnable r) {

yangshuangyue的博客 332

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Android消息处理机制——Handler

1.为什么要使用Handler? 子线程不能更改主线程的UI,在异步消息处理机制中,通过Handler完成从子线程到主线程的切换,完美解决子线程数据请求,主线程更新UI的问题 2.Handler基本原理 主线程里都维护了一个消息对列(message queue),子线程创建消息(Message),通过主线程里的Handler把消息发送到消息队列(message queue),在主线程里还有一个轮循...

qq_40575302的博客 361

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Android消息处理机制 handler looper messagequene

Android消息处理机制 2011-10-28 13:36 2396人阅读 评论(5) 收藏 举报 Google参考了Windows的消息处理机制,在Android系统中实现了一套类似的消息处理机制。学习Android的消息处理机制,有几个概念(类)必须了解: 1.       Message 消息,理解为线程间通讯的数据单元。例如后台线程在处理数据完毕后需要更新

Z153041121的专栏 1420

【Android日记】深入理解Handler消息处理机制

一、Handler的基本用法 我们可以使用一个Handler发送并处理一个线程关联的Message或者Runnable。(注意:Runnable也会被封装到Message.Callback) 基本用法 //自定义Handler创建 static class MHandler extends Handler { @Override public void handleMessage(...

平凡之路 533

不得不看的Android异步消息处理机制及Handler使用方法用法

Android中的异步消息处理主要由4个部分组成:Message、Handler、MessageQueue和Looper。 1.Message是在线程之间传递的消息

陈先森c的博客 610

Android Handler 异步消息处理机制的妙用 创建强大的图片加载类

转载请标明出处:http://blog.youkuaiyun.com/lmj623565791/article/details/38476887 ,本文出自【张鸿洋的博客】上一篇博客介绍了Android异步消息处理机制,如果你还不了解,可以看:Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系 。那篇博客的最后,提出可以把异步消息处理机制不仅仅是在MainAc

Hongyang 6万+

Android异步消息处理机制之Handler、Looper、Message

为什么用异步消息处理机制? 因为Android UI线程是线程不安全的,在子线程中更新UI会直接程序崩溃,另外当UI线程需要执行一个比较耗时的操作的话(IO操作,网络通信等),若是执行时间超过5s,程序会直接ANR,为了解决上述问题,可以使用异步消息处理机制Handler,Handler有两大用处: (1) . 在未来的某个时间点执行调度Message或者Runnable对象 (2) . 将执...

小马快跑的博客 1655

安卓开发:Handler异步消息处理机制使用

在安卓中,如果我们直接新建主线程意外的线程处理UI,是会报错的。因为安卓不能在子线程中修改UI,必须要在主线程中修改。 示例:public void onClick(View v) { if(v == button) { new Thread(new Runnable() { @Override public void run

new_Aiden的博客 350

Android Handler异步消息处理机制解读

Android Handler异步消息处理机制解读 ​ 前言 去年年底很忙,就没什么时间写博客,后面就是疫情了,疫情在老家把整个人都搞的浑浑噩噩的,提不起兴致。回到公司复工也是比较忙,没啥时间写,周末不陪陪媳妇儿还要不高兴,最近稍微空闲了一点,准备重新开始继续找回状态吧,从基础的安卓异步消息处理机制开始,网上类似博客很多,但是打算自己重新回顾一下加深印象。 开始之前 ​ 说到消息机制,大家一定非常熟悉,因为平时coding的时候高频率的使用。我们都知道,Android系统规定只能在主线程更新UI,子

whbk101的博客 722

Android异步消息处理之Handler机制

Android不允许在子线程进行UI操作。但有时必须在子线程里去执行一些耗时任务,然后根据结果更新相应的UI控件。对于这种情况,可以使用异步消息处理机制。 异步消息处理机制: Android异步消息处理主要有4个部分:Message、Handler、MessageQueue、Looper ●Message:线程中传递的消息,它可以在内部携带少量的信息。例如Message.what/arg...

LJW874362735的博客 295

安卓handler消息处理机制

Google参考了Windows的消息处理机制,在Android系统中实现了一套类似的消息处理机制。学习Android的消息处理机制,有几个概念(类)必须了解: 1.       Message 消息,理解为线程间通讯的数据单元。例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程。 2.       Message Queue 消息

zuyuanzhang自学之路 618

android的消息处理机制(Looper,Handler,Message)

一 前言 在正式剖析Handle机制的原理前,我们先来了解一下相关的术语: 通信的同步(Synchronous):只客户端在向服务器发送请求时,必须要等到服务器返回结果,客户端才会继续发送其他的请求。 通信的异步(Asynchronous) : 指客户端在发送请求后,不必等待服务端的回应就可以发送下一个请求。 所谓同步调用,就是在一个函数或方法调用时,没有得到结果之前,该调用就不返回,直到返回结果。异步调用和同步是相对的,在一个异步调用发起后,被调用者立即返回给调用者,但是调用者不能立刻得到结果,被

qq_39431405的博客 920
上一篇: 断点续传和多线程下载(二)
下一篇: 在ListView中添加item为WebView
Alone_SLFly
博客等级 码龄12年 2粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值