Android提升之一 主线程

哎,真难 2015-03-09 10:21:42
加精
好吧,最近离职好无聊,作为版主,我突发奇想,做了一个艰难的决定,每天会给大家提一问,这些问题都是面试,工作中常用到的,如果这些问题大家都搞懂了,那恭喜大家,大家已经迈过了中级工程师了,并迈向高级工程师。
好的,今天第一道问题,handler的机制,不用说了吧,那问下用handler.post或者send的时候,你怎么知道send或者post过去的是主线程,而不是子线程了?
答题思路:其实还是要结合handler,message,looper,messagequne这些来谈。
...全文
4700 37 打赏 收藏 转发到动态 举报
写回复
用AI写文章
37 条回复
切换为时间正序
请发表友善的回复…
发表回复
jeky_zhang2013 2015-09-30
  • 打赏
  • 举报
回复
平时要好好思考下,好多地方还没想通
哎,真难 2015-07-21
  • 打赏
  • 举报
回复
引用 35 楼 wf46280450 的回复:
版主您好,我目前遇到一个搜了很久都没解决的问题,是关于Android调用WebService时发生了OOM错误, SoapObject soapObject = new SoapObject(NameSpace, Method); soapObject.addProperty("part_no", “123”); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.bodyOut = soapObject; envelope.dotNet = true; HttpTransportSE httpSE = new HttpTransportSE(WSDL); try { httpSE.call(NameSpace + Method, envelope); //这里发生了OOM错误 SoapObject resultObject = (SoapObject) envelope.bodyIn; sresult = resultObject.getProperty(0).toString(); System.out.println("WebService Success"); } catch (Exception e) { System.out.println("WebService Fail--->" + e.toString()); return; } 我调用的Webservice返回的是一个很长的字符串,字符个数在几十万的时候运行正常,可是当这个返回的字符串里有几百万个字符时,在执行实际调用Webservice的那个httpSE.call语句时,根据logcat的显示,运行内存一直在增加,几秒之后就发生了内存溢出错误,导致了程序崩溃,我想请问一下有没有解决方案啊
切分分段发送
Flandre 2015-07-21
  • 打赏
  • 举报
回复
版主您好,我目前遇到一个搜了很久都没解决的问题,是关于Android调用WebService时发生了OOM错误, SoapObject soapObject = new SoapObject(NameSpace, Method); soapObject.addProperty("part_no", “123”); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.bodyOut = soapObject; envelope.dotNet = true; HttpTransportSE httpSE = new HttpTransportSE(WSDL); try { httpSE.call(NameSpace + Method, envelope); //这里发生了OOM错误 SoapObject resultObject = (SoapObject) envelope.bodyIn; sresult = resultObject.getProperty(0).toString(); System.out.println("WebService Success"); } catch (Exception e) { System.out.println("WebService Fail--->" + e.toString()); return; } 我调用的Webservice返回的是一个很长的字符串,字符个数在几十万的时候运行正常,可是当这个返回的字符串里有几百万个字符时,在执行实际调用Webservice的那个httpSE.call语句时,根据logcat的显示,运行内存一直在增加,几秒之后就发生了内存溢出错误,导致了程序崩溃,我想请问一下有没有解决方案啊
xyyliurui 2015-07-21
  • 打赏
  • 举报
回复
好厉害的样子,涨姿势了
qq_26555207 2015-03-14
  • 打赏
  • 举报
回复
打酱油 路过 来看看 哈哈哈哈
ameyume 2015-03-12
  • 打赏
  • 举报
回复
handler很常用的东东,在子线程中发送消息通知主线程更新UI等只能在主线程做的操作。
哎,真难 2015-03-11
  • 打赏
  • 举报
回复
引用 4 楼 inquisitive_plus 的回复:
我觉得从代码上来看是看handler的构造函数,handler会对自己的mLooper进行初始化, 如果是public Handler(Callback callback, boolean async)这类构造函数(包括public Handler(boolean async),public Handler(Callback callback),public Handler()) 则是mLooper = Looper.myLooper();mLooper 是当前线程looper…… 否则就是public Handler(Looper looper, Callback callback, boolean async)这样带looper的构造函数 handler有getLooper方法,就是返回mLooper 貌似可以试着用mLooper == Looper.getMainLooper()来判断是否是主线程……没试过,等下写个例子自己剩下
没注意到,不好意思,一直以为你在回复别人,,,
windfury_plus 2015-03-11
  • 打赏
  • 举报
回复
引用 26 楼 heaimnmn 的回复:
又看了一遍这个问题 ,其实问题是有问题 的,send,或post过去的不一定是主线程,也可能是子线程,因为当构建handler时在子线程中,那POST或send过去一定是在子线程 中的,这个写例子已验证!
其实就是看你的looper是在哪里实例化的,一个looper有一个MessageQueue,你的handler如果在子线程中实例化了,是否实例化looper,如果实例化就发送到子线程了,否则activity初始化的时候会初始化主线程的looper[/quote] 那我的回答呢……4楼
哎,真难 2015-03-11
  • 打赏
  • 举报
回复
引用 25 楼 liuh6 的回复:
[quote=引用 楼主 heaimnmn 的回复:] 好吧,最近离职好无聊,作为版主,我突发奇想,做了一个艰难的决定,每天会给大家提一问,这些问题都是面试,工作中常用到的,如果这些问题大家都搞懂了,那恭喜大家,大家已经迈过了中级工程师了,并迈向高级工程师。 好的,今天第一道问题,handler的机制,不用说了吧,那问下用handler.post或者send的时候,你怎么知道send或者post过去的是主线程,而不是子线程了? 答题思路:其实还是要结合handler,message,looper,messagequne这些来谈。
又看了一遍这个问题 ,其实问题是有问题 的,send,或post过去的不一定是主线程,也可能是子线程,因为当构建handler时在子线程中,那POST或send过去一定是在子线程 中的,这个写例子已验证![/quote]其实就是看你的looper是在哪里实例化的,一个looper有一个MessageQueue,你的handler如果在子线程中实例化了,是否实例化looper,如果实例化就发送到子线程了,否则activity初始化的时候会初始化主线程的looper
liuh6 2015-03-11
  • 打赏
  • 举报
回复
引用 楼主 heaimnmn 的回复:
好吧,最近离职好无聊,作为版主,我突发奇想,做了一个艰难的决定,每天会给大家提一问,这些问题都是面试,工作中常用到的,如果这些问题大家都搞懂了,那恭喜大家,大家已经迈过了中级工程师了,并迈向高级工程师。 好的,今天第一道问题,handler的机制,不用说了吧,那问下用handler.post或者send的时候,你怎么知道send或者post过去的是主线程,而不是子线程了? 答题思路:其实还是要结合handler,message,looper,messagequne这些来谈。
又看了一遍这个问题 ,其实问题是有问题 的,send,或post过去的不一定是主线程,也可能是子线程,因为当构建handler时在子线程中,那POST或send过去一定是在子线程 中的,这个写例子已验证!
liuh6 2015-03-11
  • 打赏
  • 举报
回复
引用 23 楼 heaimnmn 的回复:
[quote=引用 8 楼 liuh6 的回复:] 刚才写了个例子,验证了一下这个问题 。 1.handler实例化时如果用的主线程的looper 那通过handler的对像,发过去的消息是在主线程处理的。 如果handler实例化时如果用的子线程的looper那么通过handler的对像发送消息,是在子线程中处理。 2.要想获取handler 实例运行的线程则用:handler.getLooper().getThread().getName()来获取
答案已经很接近了,可以看下looper的源码,它是怎么获取到messagequen的[/quote] 你想表达的是这个意思,我回答的可能与你问的不是一个问题 looper的源码中写的很明白,在创建looper 对像时,在他的构造函数中初始化了一个接收处理message的队列,在启动looper的loop()方法中,一直不停的循环读取message 队列中的消息,然后回调给handler
 public static final void loop() {
        Looper me = myLooper();
        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();
        
        while (true) {
            Message msg = queue.next(); // might block
            //if (!me.mRun) {
            //    break;
            //}
            if (msg != null) {
                if (msg.target == null) {
                    // No target is a magic identifier for the quit message.
                    return;
                }
                if (me.mLogging!= null) me.mLogging.println(
                        ">>>>> Dispatching to " + msg.target + " "
                        + msg.callback + ": " + msg.what
                        );
                msg.target.dispatchMessage(msg);
                if (me.mLogging!= null) me.mLogging.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("Looper", "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();
            }
        }
    }
哎,真难 2015-03-11
  • 打赏
  • 举报
回复
引用 8 楼 liuh6 的回复:
刚才写了个例子,验证了一下这个问题 。 1.handler实例化时如果用的主线程的looper 那通过handler的对像,发过去的消息是在主线程处理的。 如果handler实例化时如果用的子线程的looper那么通过handler的对像发送消息,是在子线程中处理。 2.要想获取handler 实例运行的线程则用:handler.getLooper().getThread().getName()来获取
答案已经很接近了,可以看下looper的源码,它是怎么获取到messagequen的
  • 打赏
  • 举报
回复
dark_wing 2015-03-11
  • 打赏
  • 举报
回复
版主的帖子以及各位回复让我获益良多,我没有看过android源码,但使用起来都是以直觉来使用,平时都是handler声明的同时实例化的,其所有是主线程就是主线程,是子线程就归子线程,比较直观,倒也没有出什么问题,现在发现还有这些道道。
chengyy51 2015-03-10
  • 打赏
  • 举报
回复
这个还真不知道???
hejie1161 2015-03-10
  • 打赏
  • 举报
回复
喜欢用handler
qq_26445445 2015-03-10
  • 打赏
  • 举报
回复
laoer_2002 2015-03-10
  • 打赏
  • 举报
回复
学习
哎,真难 2015-03-10
  • 打赏
  • 举报
回复
引用 14 楼 hjywyj 的回复:
你不是说你很忙么?还闲的来逛论坛
我每天都要抽个时间来这里
  • 打赏
  • 举报
回复
你不是说你很忙么?还闲的来逛论坛
加载更多回复(13)

80,351

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧