精华内容
下载资源
问答
  • react中postMessage与addEventListener的使用

    万次阅读 2020-12-11 11:04:27
    有时候两个页面之间不是父子组件的情况下,信息交互很难搞,看到有人用postmessage来进行消息交互,我也试了一下,哎呀妈真香!!! 1、首先在需要发送消息的界面中使用postMessage 使用的是React+TypeScript,逻辑...

    有时候两个页面之间不是父子组件的情况下,信息交互很难搞,看到有人用postmessage来进行消息交互,我也试了一下,哎呀妈真香!!!

    1、首先在需要发送消息的界面中使用postMessage

    使用的是React+TypeScript,逻辑是更新提交的时候刷新打开当前页面的父窗口,postMessage用法如下:

    if (window.opener && window.opener.location && window.opener.location.href) {
                            let origin = window.opener.location.href;
                            let originStr = origin.substring(origin.length - 21, origin.length);
                            if (origin.indexOf("/tankInfoManage/valve") != -1) {
                                window.opener.postMessage("message", origin)
                            }
                            window.close();
                        }
    

    2、接收消息

    window.addEventListener('message', (e) => {
                ref.cuttent?.reload()
                ref.current?.clearSelected()
            });
    
    展开全文
  • No message available 请求不能成功

    万次阅读 2019-08-20 14:21:40
    1.No message available

    1.No message available在这里插入图片描述

    原因:路径问题–接口路径和客户端请求路径不一致

    展开全文
  • 1. 前言创建Message对象的时候,有三种方式,分别为: 1.Message msg = new Message(); 2.Message msg2 = Message.obtain(); 3.Message msg1 = handler1.obtainMessage(); 这三种方式有什么区别呢?2.使用...
    1. 前言

    创建Message对象的时候,有三种方式,分别为:
    1.Message msg = new Message();
    2.Message msg2 = Message.obtain();
    3.Message msg1 = handler1.obtainMessage();
    这三种方式有什么区别呢?

    2.使用方式

    public class MainActivity extends Activity {
    
        private Handler handler1 = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                Toast.makeText(MainActivity.this, "hanlder1", Toast.LENGTH_SHORT).show();
                super.handleMessage(msg);
            }
        };
        ;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            new Thread(new Runnable() {
                @Override
                public void run() {
    //                Message msg = new Message();
    //                Message msg2 = Message.obtain();
                    Message msg1 = handler1.obtainMessage();
                    msg1.arg1 = 1;
                    handler1.sendMessage(msg1);
                }
            }).start();
        }
    }
    

    3.源码讲解

    1)Message msg = new Message();这种就是直接初始化一个Message对象,没有什么特别的。
    2)Message msg2 = Message.obtain();

    /**
         * Return a new Message instance from the global pool. Allows us to
         * avoid allocating new objects in many cases.
         */
        public static Message obtain() {
            synchronized (sPoolSync) {
                if (sPool != null) {
                    Message m = sPool;
                    sPool = m.next;
                    m.next = null;
                    m.flags = 0; // clear in-use flag
                    sPoolSize--;
                    return m;
                }
            }
            return new Message();
        }
    

    从注释可以得知,从整个Messge池中返回一个新的Message实例,通过obtainMessage能避免重复Message创建对象。
    3)Message msg1 = handler1.obtainMessage();

    public final Message obtainMessage()
        {
            return Message.obtain(this);
        }
    
    public static Message obtain(Handler h) {
            Message m = obtain();
            m.target = h;
    
            return m;
        }
    
    public static Message obtain() {
            synchronized (sPoolSync) {
                if (sPool != null) {
                    Message m = sPool;
                    sPool = m.next;
                    m.next = null;
                    m.flags = 0; // clear in-use flag
                    sPoolSize--;
                    return m;
                }
            }
            return new Message();
        }
    

    可以看到,第二种跟第三种其实是一样的,都可以避免重复创建Message对象,所以建议用第二种或者第三种任何一个创建Message对象。
    详细的源码讲解请看下篇:源码角度讲解Android消息处理机制(Handler、Looper、MessageQueue与Message)


    如有错误欢迎指出来,一起学习。
    在这里插入图片描述

    展开全文
  • 转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38377229 ,本文出自【张鸿洋的博客】很多人面试肯定都被问到过,请问Android中的Looper , Handler , Message有什么关系?本篇博客目的首先为...

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38377229 ,本文出自【张鸿洋的博客】

    很多人面试肯定都被问到过,请问Android中的Looper , Handler , Message有什么关系?本篇博客目的首先为大家从源码角度介绍3者关系,然后给出一个容易记忆的结论。

    1、 概述

    Handler 、 Looper 、Message 这三者都与Android异步消息处理线程相关的概念。那么什么叫异步消息处理线程呢?
    异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数,执行完成一个消息后则继续循环。若消息队列为空,线程则会阻塞等待。

    说了这一堆,那么和Handler 、 Looper 、Message有啥关系?其实Looper负责的就是创建一个MessageQueue,然后进入一个无限循环体不断从该MessageQueue中读取消息,而消息的创建者就是一个或多个Handler 。

    2、 源码解析

    1、Looper

    对于Looper主要是prepare()和loop()两个方法。
    首先看prepare()方法
    public static final void prepare() {
            if (sThreadLocal.get() != null) {
                throw new RuntimeException("Only one Looper may be created per thread");
            }
            sThreadLocal.set(new Looper(true));
    }
    

    sThreadLocal是一个ThreadLocal对象,可以在一个线程中存储变量。可以看到,在第5行,将一个Looper的实例放入了ThreadLocal,并且2-4行判断了sThreadLocal是否为null,否则抛出异常。这也就说明了Looper.prepare()方法不能被调用两次,同时也保证了一个线程中只有一个Looper实例~相信有些哥们一定遇到这个错误。
    下面看Looper的构造方法:
    private Looper(boolean quitAllowed) {
            mQueue = new MessageQueue(quitAllowed);
            mRun = true;
            mThread = Thread.currentThread();
    }
    
    在构造方法中,创建了一个MessageQueue(消息队列)。
    然后我们看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();
            }
    }
    

    第2行:
    public static Looper myLooper() {
    return sThreadLocal.get();
    }
    方法直接返回了sThreadLocal存储的Looper实例,如果me为null则抛出异常,也就是说looper方法必须在prepare方法之后运行。
    第6行:拿到该looper实例中的mQueue(消息队列)
    13到45行:就进入了我们所说的无限循环。
    14行:取出一条消息,如果没有消息则阻塞。
    27行:使用调用 msg.target.dispatchMessage(msg);把消息交给msg的target的dispatchMessage方法去处理。Msg的target是什么呢?其实就是handler对象,下面会进行分析。
    44行:释放消息占据的资源。

    Looper主要作用:
    1、 与当前线程绑定,保证一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue。
    2、 loop()方法,不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。
    好了,我们的异步消息处理线程已经有了消息队列(MessageQueue),也有了在无限循环体中取出消息的哥们,现在缺的就是发送消息的对象了,于是乎:Handler登场了。

    2、Handler

    使用Handler之前,我们都是初始化一个实例,比如用于更新UI线程,我们会在声明的时候直接初始化,或者在onCreate中初始化Handler实例。所以我们首先看Handler的构造方法,看其如何与MessageQueue联系上的,它在子线程中发送的消息(一般发送消息都在非UI线程)怎么发送到MessageQueue中的。
    public Handler() {
            this(null, false);
    }
    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;
        }
    

    14行:通过Looper.myLooper()获取了当前线程保存的Looper实例,然后在19行又获取了这个Looper实例中保存的MessageQueue(消息队列),这样就保证了handler的实例与我们Looper实例中MessageQueue关联上了。

    然后看我们最常用的sendMessage方法

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

       public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
            Message msg = Message.obtain();
            msg.what = what;
            return sendMessageDelayed(msg, delayMillis);
        }

     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);
        }

    辗转反则最后调用了sendMessageAtTime,在此方法内部有直接获取MessageQueue然后调用了enqueueMessage方法,我们再来看看此方法:

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

    enqueueMessage中首先为meg.target赋值为this,【如果大家还记得Looper的loop方法会取出每个msg然后交给msg,target.dispatchMessage(msg)去处理消息】,也就是把当前的handler作为msg的target属性。最终会调用queue的enqueueMessage的方法,也就是说handler发出的消息,最终会保存到消息队列中去。


    现在已经很清楚了Looper会调用prepare()和loop()方法,在当前执行的线程中保存一个Looper实例,这个实例会保存一个MessageQueue对象,然后当前线程进入一个无限循环中去,不断从MessageQueue中读取Handler发来的消息。然后再回调创建这个消息的handler中的dispathMessage方法,下面我们赶快去看一看这个方法:

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

    可以看到,第10行,调用了handleMessage方法,下面我们去看这个方法:

      /**
         * Subclasses must implement this to receive messages.
         */
        public void handleMessage(Message msg) {
        }
        
    可以看到这是一个空方法,为什么呢,因为消息的最终回调是由我们控制的,我们在创建handler的时候都是复写handleMessage方法,然后根据msg.what进行消息处理。

    例如:

    private Handler mHandler = new Handler()
    	{
    		public void handleMessage(android.os.Message msg)
    		{
    			switch (msg.what)
    			{
    			case value:
    				
    				break;
    
    			default:
    				break;
    			}
    		};
    	};

    到此,这个流程已经解释完毕,让我们首先总结一下

    1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。

    2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。

    3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。

    4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。

    5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。

    好了,总结完成,大家可能还会问,那么在Activity中,我们并没有显示的调用Looper.prepare()和Looper.loop()方法,为啥Handler可以成功创建呢,这是因为在Activity的启动代码中,已经在当前UI线程调用了Looper.prepare()和Looper.loop()方法。

    3、Handler post

    今天有人问我,你说Handler的post方法创建的线程和UI线程有什么关系?

    其实这个问题也是出现这篇博客的原因之一;这里需要说明,有时候为了方便,我们会直接写如下代码:

    mHandler.post(new Runnable()
    		{
    			@Override
    			public void run()
    			{
    				Log.e("TAG", Thread.currentThread().getName());
    				mTxt.setText("yoxi");
    			}
    		});

    然后run方法中可以写更新UI的代码,其实这个Runnable并没有创建什么线程,而是发送了一条消息,下面看源码:

     public final boolean post(Runnable r)
        {
           return  sendMessageDelayed(getPostMessage(r), 0);
        }
      private static Message getPostMessage(Runnable r) {
            Message m = Message.obtain();
            m.callback = r;
            return m;
        }

    可以看到,在getPostMessage中,得到了一个Message对象,然后将我们创建的Runable对象作为callback属性,赋值给了此message.

    注:产生一个Message对象,可以new  ,也可以使用Message.obtain()方法;两者都可以,但是更建议使用obtain方法,因为Message内部维护了一个Message池用于Message的复用,避免使用new 重新分配内存。

     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);
        }
    最终和handler.sendMessage一样,调用了sendMessageAtTime,然后调用了enqueueMessage方法,给msg.target赋值为handler,最终加入MessagQueue.

    可以看到,这里msg的callback和target都有值,那么会执行哪个呢?

    其实上面已经贴过代码,就是dispatchMessage方法:

     public void dispatchMessage(Message msg) {
            if (msg.callback != null) {
                handleCallback(msg);
            } else {
                if (mCallback != null) {
                    if (mCallback.handleMessage(msg)) {
                        return;
                    }
                }
                handleMessage(msg);
            }
        }
    第2行,如果不为null,则执行callback回调,也就是我们的Runnable对象。

    好了,关于Looper , Handler , Message 这三者关系上面已经叙述的非常清楚了。

    最后来张图解:


    希望图片可以更好的帮助大家的记忆~~

    4、后话

    其实Handler不仅可以更新UI,你完全可以在一个子线程中去创建一个Handler,然后使用这个handler实例在任何其他线程中发送消息,最终处理消息的代码都会在你创建Handler实例的线程中运行。

    new Thread()
    		{
    			private Handler handler;
    			public void run()
    			{
    
    				Looper.prepare();
    				
    				handler = new Handler()
    				{
    					public void handleMessage(android.os.Message msg)
    					{
    						Log.e("TAG",Thread.currentThread().getName());
    					};
    				};
                                   Looper.loop();                                                                                                                              }             

    Android不仅给我们提供了异步消息处理机制让我们更好的完成UI的更新,其实也为我们提供了异步消息处理机制代码的参考~~不仅能够知道原理,最好还可以将此设计用到其他的非Android项目中去~~

    最新补充:

    关于后记,有兄弟联系我说,到底可以在哪使用,见博客:Android Handler 异步消息处理机制的妙用 创建强大的图片加载类




    展开全文
  • jQuery Message

    千次阅读 2019-01-14 10:28:18
    jQuery Message jQuery Message 插件允许您很容易地在一个覆盖层显示反馈消息。消息会在一段时间后自动消失,不需要单击"确定"按钮等。用户可以通过移动鼠标或点击任何地方加快隐藏信息。 访问 jQuery ...
  • MessageID

    千次阅读 2019-03-22 10:37:10
    MessageID是在发送时才确定好的,所以在message发送前,使用提供的setMessageId设置新的Id也没有作用 另外,topic下同一条消息发送至不同的消费者,但是所有消息ID是一致的。因为广播模式只是按照订阅者数量,将消息...
  • postMessage

    千次阅读 2018-09-19 08:23:38
    postMessage(data,origin)方法接受两个参数 demo a.html &lt;iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"&gt;&lt;/iframe&gt; ...
  •         今天在做selenium测试的时候,可能是很久没用了,直接报了这个异常! ...相信很多第一次学习selenium的同学们也对这个异常不陌生了,但具体该如何解决这个bug呢?...
  • 很多小伙伴可能会在实际的...官方文档的描述是这样 : " 调用 Message 或 this.$message 会返回当前 Message 的实例。如果需要手动关闭实例,可以调用它的 close 方法。" 所以贴上亲测有效的代码 OnOfflineStatus
  • PCIe中的Message

    千次阅读 2019-06-05 21:35:29
    PCIe中的Message主要是为了替代PCI中采用边带信号,这些边带信号的主要功能是中断,错误报告和电源管理等。所有的Message请求采用的都是4DW的TLP Header,但是并不是所有的空间都被利用上了,例如有的Message就没有...
  • 谷歌推荐:Message.obtain() Message.obtain(),在这里我们的Message已经不是自己创建的了,而是从MessagePool(消息池)拿的,省去了创建对象申请内存的开销。 &lt;script type="text/javascript"&...
  • Message 如何获取一个消息 Message.obtain() 消息的回收利用 MessageQueue MessageQueue 的属性 何时初始化 消息入队的过程 消息出队的过程 Looper 线程相关 ThreadLocal 无限循环调度 如何停止 Handler ...
  • vue消息提示this.$message方法

    万次阅读 2019-03-24 22:30:25
    //弹出信息 alertMessage(action,a){ var msg,type; switch(a){ case '1': type='success'; msg = ...
  • Message:Message: 前言中不允许有内容

    千次阅读 2020-01-11 17:01:26
    Message: 前言中不允许有内容。 1.右键出错的文件,Remove BOM 2.打开设置,Editor ——》File Encoding 选择with no BOM,注意:这个设置只修改了当前项目,如果还需要为其他项目设置,在other settings 为新的...
  • 本文是从源码的角度对andorid异步消息处理机制的梳理,那么在文章开始阶段,先简单介绍,异步消息处理机制中各部件的作用以及处理处理机制的概述1、Handler、MessageMessageQueue、Looper功能简述Handler负责消息...
  • PB的message用法之message.stringparm

    千次阅读 2016-07-28 17:49:03
    message.stringparm[@more@] 在powerbuilder中有一个message对象,它的一个属性是stringparm: 窗口之间传数据信息!比如搜索条件等, 比如你 openwithparm(w_1,'abc') 你在w_1的open事件里就可以通过message....
  • tomcat 应用Message file 'oracle net mesg Message' is missing问题
  • 目前的情况是message 选项卡只显示当前打开的文件的message,请问如何才能让其显示整个解决方案中的所有message
  • Android7.0 MessageQueue

    千次阅读 2016-09-21 22:37:42
    每个Handler都有对应的Looper,用于不断地从对应的MessageQueue中取出消息处理。 一直以来,觉得MessageQueue应该是Java层的抽象,然而事实上MessageQueue的主要部分在Native层中。 自己对MessageQueue在Native层...
  • 深入源码解析Android中的Handler,Message,MessageQueue,Looper

    万次阅读 多人点赞 2015-08-01 02:20:53
    本文主要是对Handler和消息循环的实现原理进行源码分析,通过分析源码的方式去探索Thread、MessageQueue、Looper、Message以及Handler的实现原理,并最终通过一张图的形式将它们之间的关系展示出来。
  • 一篇文章深入分析Handler源码Handler概述Message 消息对象MessageQueue: 消息队列的源码分析 Handler概述 Handler是一种通信机制,只不过在Android我们常用来更新UI,接下来我将分别从MessageMessageQueue、...
  • ChannelAwareMessageListener 与MessageListener

    万次阅读 2017-12-13 23:35:57
    在使用Spring amqp创建消费者并接收消息时,通常会用到下面两个接口。... void onMessage(Message message); } public interface ChannelAwareMessageListener { void onMessage(Message message,
  • Vue的Element确实给开发者提供了很大的便捷,比如消息提示中的:this.$message 函数就非常好用。但是在某些情况下是失效的,比如如下代码所示: onSubmit: function () { if (this.formInline.title === '') { /...
  • 修改commit的message

    千次阅读 2019-08-10 00:06:35
    对最近commit的message进行修改: git commit --amend 会弹出一个文本让你修改,第一行就是描述用的message 对以前提交的commit的message进行修改(较难) 如果我们要修改“子”这条commit的message,我们要...
  • vue element-ui message或this.$message 主动关闭 ヤッハロー、Kaiqisanすうう、一つふつうの学生プログラマである, 在我实际的项目过程中,赶巧不巧碰到服务器特别迟缓的时候,有时候在向后端请求信息的时候,会...
  • 遇到下面异常: E/InputEventReceiver: Exception dispatching input ...E/MessageQueue-JNI: Exception in MessageQueue callback: handleReceiveCallback E/MessageQueue-JNI: java.lang.NullPointerException: Atte
  • 解决 iframe.postMessage()多次触发请求问题 方法一,将addEventListener改成onmessage window.addEventListener(‘message’, (e) => {})多次调用会多次生成不同的匿名函数e,应指向同一个命名函数 window....
  • 创建Message对象的时候,有三种方式,分别为: 1.Message msg = new Message(); 2.Message msg1 = Message.obtain(); 3.Message msg2 = handler.obtainMessage(); 这三种方式有什么区别呢?使用方式:public ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 551,313
精华内容 220,525
关键字:

message