Android Performance(3) Hierarchy Viewer


转载请注明:http://blog.csdn.net/liaoqianchuan00/article/details/23542373 

概述

Hierarchy Viewer允许你调试和优化你的UI界面,他向开发人员展示一个视图的层次结构,以及每个laytout中节点的performance信息。

 

功能介绍

打开Hierarchy View:Window->Open Perspective->Other..->HierarchyView.

选择我们要分析程序。点击下图所示红色图标位置。可以看见右边有3个面板,有Tree View, Tree Overview, Layout View。如果没有显示这些面板,可以在Window->Show View中选择打开。

 

 

                                                                                                       

 

1.     TreeView

l   可以放大缩小TreeView,也可以点击拖拽来查看其他节点。

l   在Filter byclass or id输入框中输入string来查找相应的class或者id,比如查找textView3.找到的节点背景色将变为蓝色。

l   也可以点击TreeView面板上方的按钮来保存图片。

l   每个View节点中可以显示ViewClass,Object 地址,View ID,Performance的圆圈,View序号(在父控件中的序号,从0开始)

l   点击TreeView中得ListView节点,可以看见他上方出现了一个屏幕上该控件的缩略图。如下图。我们也可以点击Layout view中得相应控件来快速找到一个View。

 

l   接着我们点击下图中红色方框中得图标,可以看到ListView中包含的控件节点都多了3个原点,这3个原点有绿黄红三种颜色,黄色和红色表示耗时久。绿色正常,而第一个点表示计算这个View size的时间。第二个点表示创建这个view的时间。第三个点表示在屏幕上画这个view的消耗时间。


 

2.     TreeOverView

你可以使用Tree OverView来更方便的移动TreeView视图。

3.     PropertiesView

你选中的View节点的属性列表,你可以很方便的查看这些属性而不需要去查看源代码。

4.     Layout View

另外一种展现View结构的方式,当你在TreeView中选中一个节点的时候,Layout View中会用红色来显示选中View的位置和大小等。在这个面板中,当你选中一个View的时候,会同时显示红色,白色,和浅红色区域,

l   红色:当前选中的view

l   浅红色:当前选中View的父控件。

l   白色:既不是当前选中View的父控件,也不是他得子空间。

 

问题:

为了安全性的保护,Hierarchy只能连接到开发者版本的android系统,如果你的机器是在商店或者运营商提供的机器,那么就会连接失败。解决方法是可以root你的机器,或者是用到ViewServer

 

[2014-04-12 14:45:53 - ViewServerDevice]Unable todebug device: samsung-sm_n9008v-5d1a632d

[2014-04-12 14:45:53 - hierarchyviewer]Missingforwarded port for 5d1a632d

 

1.    从https://github.com/romainguy/ViewServer处下载ViewServer文件,加入项目中,

2.    并且在Manifest中添加权限

<uses-permissionandroid:name="android.permission.INTERNET"/>

3.    在相应的Activity的onCreate,OnDestroy,onResume中添加相应的方法。

具体方法可参照ViewServer类的javadoc。

/*

 * Copyright(C) 2011 The Android Open Source Project

 *

 * Licensedunder the Apache License, Version 2.0 (the "License");

 * you may notuse this file except in compliance with the License.

 * You mayobtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unlessrequired by applicable law or agreed to in writing, software

 * distributedunder the License is distributed on an "AS IS" BASIS,

 * WITHOUTWARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See theLicense for the specific language governing permissions and

 * limitationsunder the License.

 */

 

package com.example.androidtest;

 

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.OutputStreamWriter;

import java.lang.reflect.Method;

import java.net.InetAddress;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.HashMap;

import java.util.List;

import java.util.Map.Entry;

import java.util.concurrent.CopyOnWriteArrayList;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

importjava.util.concurrent.locks.ReentrantReadWriteLock;

 

import android.app.Activity;

import android.content.Context;

import android.content.pm.ApplicationInfo;

import android.os.Build;

import android.text.TextUtils;

import android.util.Log;

import android.view.View;

import android.view.ViewDebug;

 

/**

 *<p>This class can be used to enable the use of HierarchyViewer inside an

 * application.HierarchyViewer is an Android SDK tool that can be used

 * to inspectand debug the user interface of running applications. For

 * securityreasons, HierarchyViewer does not work on production builds

 * (forinstance phones bought in store.) By using this class, you can

 * makeHierarchyViewer work on any device. You must be very careful

 * however toonly enable HierarchyViewer when debugging your

 *application.</p>

 *

 * <p>Touse this view server, your application must require the INTERNET

 *permission.</p>

 *

 * <p>Therecommended way to use this API is to register activities when

 * they arecreated, and to unregister them when they get destroyed:</p>

 *

 * <pre>

 * public classMyActivity extends Activity {

 *     public void onCreate(BundlesavedInstanceState) {

 *         super.onCreate(savedInstanceState);

 *         // Set content view, etc.

 *         ViewServer.get(this).addWindow(this);

 *     }

 *      

 *     public void onDestroy() {

 *         super.onDestroy();

 *        ViewServer.get(this).removeWindow(this);

 *     }

 *  

 *     public void onResume() {

 *         super.onResume();

 *        ViewServer.get(this).setFocusedWindow(this);

 *     }

 * }

 * </pre>

 *

 * <p>

 * In a similarfashion, you can use this API with an InputMethodService:

 * </p>

 *

 * <pre>

 * public classMyInputMethodService extends InputMethodService {

 *     public void onCreate() {

 *         super.onCreate();

 *         View decorView =getWindow().getWindow().getDecorView();

 *         String name ="MyInputMethodService";

 *        ViewServer.get(this).addWindow(decorView, name);

 *     }

 *

 *     public void onDestroy() {

 *         super.onDestroy();

 *         View decorView =getWindow().getWindow().getDecorView();

 *        ViewServer.get(this).removeWindow(decorView);

 *     }

 *

 *     public void onStartInput(EditorInfoattribute, boolean restarting) {

 *         super.onStartInput(attribute,restarting);

 *         View decorView =getWindow().getWindow().getDecorView();

 *        ViewServer.get(this).setFocusedWindow(decorView);

 *     }

 * }

 * </pre>

 */

public class ViewServer implements Runnable {

    /**

     * Thedefault port used to start view servers.

     */

    privatestatic final int VIEW_SERVER_DEFAULT_PORT = 4939;

    privatestatic final int VIEW_SERVER_MAX_CONNECTIONS = 10;

    privatestatic final String BUILD_TYPE_USER = "user";

 

    // Debugfacility

    privatestatic final String LOG_TAG = "ViewServer";

 

    privatestatic final String VALUE_PROTOCOL_VERSION = "4";

    privatestatic final String VALUE_SERVER_VERSION = "4";

 

    // Protocolcommands

    // Returnsthe protocol version

    privatestatic final String COMMAND_PROTOCOL_VERSION = "PROTOCOL";

    // Returnsthe server version

    privatestatic final String COMMAND_SERVER_VERSION = "SERVER";

    // Listsall of the available windows in the system

    private staticfinal String COMMAND_WINDOW_MANAGER_LIST = "LIST";

    // Keeps aconnection open and notifies when the list of windows changes

    privatestatic final String COMMAND_WINDOW_MANAGER_AUTOLIST = "AUTOLIST";

    // Returnsthe focused window

    privatestatic final String COMMAND_WINDOW_MANAGER_GET_FOCUS = "GET_FOCUS";

 

    privateServerSocket mServer;

    privatefinal int mPort;

 

    privateThread mThread;

    privateExecutorService mThreadPool;

   

    privatefinal List<WindowListener> mListeners =

        newCopyOnWriteArrayList<ViewServer.WindowListener>();

 

    privatefinal HashMap<View, String> mWindows = new HashMap<View, String>();

    privatefinal ReentrantReadWriteLock mWindowsLock = new ReentrantReadWriteLock();

 

    privateView mFocusedWindow;

    privatefinal ReentrantReadWriteLock mFocusLock = new ReentrantReadWriteLock();

 

    privatestatic ViewServer sServer;

 

    /**

     * Returnsa unique instance of the ViewServer. This method should only be

     * calledfrom the main thread of your application. The server will have

     * the samelifetime as your process.

     *

     * If yourapplication does not have the <code>android:debuggable</code>

     * flag setin its manifest, the server returned by this method will

     * be adummy object that does not do anything. This allows you to use

     * the samecode in debug and release versions of your application.

     *

     * @paramcontext A Context used to check whether the application is

     *                debuggable, this can be theapplication context

     */

    publicstatic ViewServer get(Context context) {

       ApplicationInfo info = context.getApplicationInfo();

        if(BUILD_TYPE_USER.equals(Build.TYPE) &&

               (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {

            if(sServer == null) {

               sServer = new ViewServer(ViewServer.VIEW_SERVER_DEFAULT_PORT);

            }

   

            if(!sServer.isRunning()) {

               try {

                   sServer.start();

                } catch (IOException e) {

                   Log.d(LOG_TAG, "Error:", e);

               }

            }

        } else{

           sServer = new NoopViewServer();

        }

 

        returnsServer;

    }

 

    privateViewServer() {

        mPort =-1;

    }

   

    /**

     * Createsa new ViewServer associated with the specified window manager on the

     *specified local port. The server is not started by default.

     *

     * @paramport The port for the server to listen to.

     *

     * @see #start()

     */

    privateViewServer(int port) {

        mPort =port;

    }

 

    /**

     * Startsthe server.

     *

     * @returnTrue if the server was successfully created, or false if it already exists.

     * @throwsIOException If the server cannot be created.

     *

     * @see#stop()

     * @see#isRunning()

     * @seeWindowManagerService#startViewServer(int)

     */

    publicboolean start() throws IOException {

        if(mThread != null) {

           return false;

        }

 

        mThread = new Thread(this, "LocalView Server [port=" + mPort + "]");

       mThreadPool = Executors.newFixedThreadPool(VIEW_SERVER_MAX_CONNECTIONS);

       mThread.start();

 

        returntrue;

    }

 

    /**

     * Stopsthe server.

     *

     * @return True if the server was stopped,false if an error occurred or if the

     *         server wasn't started.

     *

     * @see#start()

     * @see#isRunning()

     * @seeWindowManagerService#stopViewServer()

     */

    publicboolean stop() {

        if(mThread != null) {

           mThread.interrupt();

            if(mThreadPool != null) {

               try {

                   mThreadPool.shutdownNow();

               } catch (SecurityException e) {

                   Log.w(LOG_TAG, "Could not stop all view server threads");

               }

            }

 

           mThreadPool = null;

           mThread = null;

 

            try{

               mServer.close();

               mServer = null;

               return true;

            } catch (IOException e) {

               Log.w(LOG_TAG, "Could not close the view server");

            }

        }

 

       mWindowsLock.writeLock().lock();

        try {

           mWindows.clear();

        }finally {

           mWindowsLock.writeLock().unlock();

        }

 

       mFocusLock.writeLock().lock();

        try {

           mFocusedWindow = null;

        }finally {

           mFocusLock.writeLock().unlock();

        }

 

        returnfalse;

    }

 

    /**

     *Indicates whether the server is currently running.

     *

     * @returnTrue if the server is running, false otherwise.

     *

     * @see#start()

     * @see#stop()

     * @seeWindowManagerService#isViewServerRunning() 

     */

    publicboolean isRunning() {

        return mThread != null &&mThread.isAlive();

    }

   

    /**

     * Invokethis method to register a new view hierarchy.

     *

     * @paramactivity The activity whose view hierarchy/window to register

     *

     * @see#addWindow(View, String)

     * @see #removeWindow(Activity)

     */

    public voidaddWindow(Activity activity) {

        Stringname = activity.getTitle().toString();

        if(TextUtils.isEmpty(name)) {

           name = activity.getClass().getCanonicalName() +

                    "/0x" +System.identityHashCode(activity);

        } else{

           name += "(" + activity.getClass().getCanonicalName() +")";

        }

       addWindow(activity.getWindow().getDecorView(), name);

    }

 

    /**

     * Invokethis method to unregister a view hierarchy.

     *

     * @paramactivity The activity whose view hierarchy/window to unregister

     *

     * @see#addWindow(Activity)

     * @see#removeWindow(View)

     */

    public voidremoveWindow(Activity activity) {

        removeWindow(activity.getWindow().getDecorView());

    }

 

    /**

     * Invokethis method to register a new view hierarchy.

     *

     * @paramview A view that belongs to the view hierarchy/window to register

     * @namename The name of the view hierarchy/window to register

     *

     * @see#removeWindow(View)

     */

    public voidaddWindow(View view, String name) {

       mWindowsLock.writeLock().lock();

        try {

           mWindows.put(view.getRootView(), name);

        }finally {

            mWindowsLock.writeLock().unlock();

        }

       fireWindowsChangedEvent();

    }

 

    /**

     * Invokethis method to unregister a view hierarchy.

     *

     * @paramview A view that belongs to the view hierarchy/window to unregister

     *

     * @see#addWindow(View, String)

     */

    public voidremoveWindow(View view) {

       mWindowsLock.writeLock().lock();

        try {

           mWindows.remove(view.getRootView());

        }finally {

           mWindowsLock.writeLock().unlock();

        }

       fireWindowsChangedEvent();

    }

 

    /**

     * Invokethis method to change the currently focused window.

     *

     * @paramactivity The activity whose view hierarchy/window hasfocus,

     *                 or null to remove focus

     */

    public voidsetFocusedWindow(Activity activity) {

       setFocusedWindow(activity.getWindow().getDecorView());

    }

   

    /**

     * Invokethis method to change the currently focused window.

     *

     * @paramview A view that belongs to the view hierarchy/window that has focus,

     *             or null to remove focus

     */

    public voidsetFocusedWindow(View view) {

       mFocusLock.writeLock().lock();

        try {

           mFocusedWindow = view == null ? null : view.getRootView();

        }finally {

           mFocusLock.writeLock().unlock();

        }

       fireFocusChangedEvent();

    }

 

    /**

     * Mainserver loop.

     */

    public voidrun() {

        try {

           mServer = new ServerSocket(mPort, VIEW_SERVER_MAX_CONNECTIONS,InetAddress.getLocalHost());

        } catch(Exception e) {

           Log.w(LOG_TAG, "Starting ServerSocket error: ", e);

        }

 

        while(mServer != null && Thread.currentThread() == mThread) {

            //Any uncaught exception will crash the system process

            try{

               Socket client = mServer.accept();

               if (mThreadPool != null) {

                   mThreadPool.submit(new ViewServerWorker(client));

               } else {

                    try {

                        client.close();

                   } catch (IOException e) {

                        e.printStackTrace();

                   }

               }

            }catch (Exception e) {

               Log.w(LOG_TAG, "Connection error: ", e);

            }

        }

    }

 

    privatestatic boolean writeValue(Socket client, String value) {

        booleanresult;

       BufferedWriter out = null;

        try {

           OutputStream clientStream = client.getOutputStream();

            out= new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);

           out.write(value);

           out.write("\n");

           out.flush();

           result = true;

        } catch(Exception e) {

           result = false;

        }finally {

            if(out != null) {

               try {

                   out.close();

               } catch (IOException e) {

                   result = false;

               }

            }

        }

        returnresult;

    }

   

    privatevoid fireWindowsChangedEvent() {

        for(WindowListener listener : mListeners) {

           listener.windowsChanged();

        }

    }

 

    privatevoid fireFocusChangedEvent() {

        for(WindowListener listener : mListeners) {

           listener.focusChanged();

        }

    }

   

    privatevoid addWindowListener(WindowListener listener) {

        if(!mListeners.contains(listener)) {

           mListeners.add(listener);

        }

    }

 

    privatevoid removeWindowListener(WindowListener listener) {

       mListeners.remove(listener);

    }

 

    privateinterface WindowListener {

        voidwindowsChanged();

        voidfocusChanged();

    }

   

    privatestatic class UncloseableOutputStream extends OutputStream {

        privatefinal OutputStream mStream;

 

       UncloseableOutputStream(OutputStream stream) {

           mStream = stream;

        }

 

        publicvoid close() throws IOException {

            //Don't close the stream

        }

 

        public boolean equals(Object o) {

           return mStream.equals(o);

        }

 

        publicvoid flush() throws IOException {

           mStream.flush();

        }

 

        publicint hashCode() {

           return mStream.hashCode();

        }

 

        public String toString() {

           return mStream.toString();

        }

 

        publicvoid write(byte[] buffer, int offset, int count)

               throws IOException {

           mStream.write(buffer, offset, count);

        }

 

        publicvoid write(byte[] buffer) throws IOException {

           mStream.write(buffer);

        }

 

        publicvoid write(int oneByte) throws IOException {

           mStream.write(oneByte);

        }

    }

 

    privatestatic class NoopViewServer extends ViewServer {

        privateNoopViewServer() {

        }

 

       @Override

        publicboolean start() throws IOException {

           return false;

        }

 

       @Override

        publicboolean stop() {

           return false;

        }

 

       @Override

        publicboolean isRunning() {

           return false;

        }

 

       @Override

        publicvoid addWindow(Activity activity) {

        }

 

       @Override

        publicvoid removeWindow(Activity activity) {

        }

 

        @Override

        publicvoid addWindow(View view, String name) {

        }

 

       @Override

        publicvoid removeWindow(View view) {

        }

 

       @Override

        publicvoid setFocusedWindow(Activity activity) {

        }

 

        @Override

        publicvoid setFocusedWindow(View view) {

        }

 

       @Override

        publicvoid run() {

        }

    }

 

    privateclass ViewServerWorker implements Runnable, WindowListener {

        privateSocket mClient;

        privateboolean mNeedWindowListUpdate;

        privateboolean mNeedFocusedWindowUpdate;

 

        privatefinal Object[] mLock = new Object[0];

 

        publicViewServerWorker(Socket client) {

           mClient = client;

           mNeedWindowListUpdate = false;

           mNeedFocusedWindowUpdate = false;

        }

 

        publicvoid run() {

           BufferedReader in = null;

            try{

               in = new BufferedReader(new InputStreamReader(mClient.getInputStream()),1024);

 

               final String request = in.readLine();

 

               String command;

               String parameters;

 

               int index = request.indexOf(' ');

               if (index == -1) {

                   command = request;

                   parameters = "";

               } else {

                   command = request.substring(0, index);

                   parameters = request.substring(index + 1);

               }

 

               boolean result;

               if (COMMAND_PROTOCOL_VERSION.equalsIgnoreCase(command)) {

                   result = writeValue(mClient, VALUE_PROTOCOL_VERSION);

               } else if (COMMAND_SERVER_VERSION.equalsIgnoreCase(command)) {

                   result = writeValue(mClient, VALUE_SERVER_VERSION);

                } else if(COMMAND_WINDOW_MANAGER_LIST.equalsIgnoreCase(command)) {

                   result = listWindows(mClient);

               } else if (COMMAND_WINDOW_MANAGER_GET_FOCUS.equalsIgnoreCase(command)) {

                   result = getFocusedWindow(mClient);

               } else if (COMMAND_WINDOW_MANAGER_AUTOLIST.equalsIgnoreCase(command)) {

                   result = windowManagerAutolistLoop();

               } else {

                   result = windowCommand(mClient, command, parameters);

               }

 

               if (!result) {

                   Log.w(LOG_TAG, "An error occurred with the command: " +command);

               }

            }catch(IOException e) {

               Log.w(LOG_TAG, "Connection error: ", e);

            }finally {

               if (in != null) {

                   try {

                        in.close();

 

                   } catch (IOException e) {

                        e.printStackTrace();

                   }

               }

                if (mClient != null) {

                   try {

                        mClient.close();

                   } catch (IOException e) {

                        e.printStackTrace();

                   }

               }

            }

        }

 

        privateboolean windowCommand(Socket client, String command, String parameters) {

           boolean success = true;

           BufferedWriter out = null;

 

            try{

               // Find the hash code of the window

               int index = parameters.indexOf(' ');

               if (index == -1) {

                   index = parameters.length();

               }

               final String code = parameters.substring(0, index);

               int hashCode = (int) Long.parseLong(code, 16);

 

               // Extract the command's parameter after the window description

               if (index < parameters.length()) {

                   parameters = parameters.substring(index + 1);

               } else {

                   parameters = "";

               }

 

               final View window = findWindow(hashCode);

               if (window == null) {

                   return false;

               }

               

               // call stuff

               final Method dispatch =ViewDebug.class.getDeclaredMethod("dispatchCommand",

                        View.class,String.class, String.class, OutputStream.class);

               dispatch.setAccessible(true);

               dispatch.invoke(null, window, command, parameters,

                        newUncloseableOutputStream(client.getOutputStream()));

 

               if (!client.isOutputShutdown()) {

                   out = new BufferedWriter(newOutputStreamWriter(client.getOutputStream()));

                   out.write("DONE\n");

                   out.flush();

               }

 

            }catch (Exception e) {

               Log.w(LOG_TAG, "Could not send command " + command +

                        " with parameters" + parameters, e);

               success = false;

            }finally {

               if (out != null) {

                   try {

                        out.close();

                   } catch (IOException e) {

                        success = false;

                   }

                }

            }

 

           return success;

        }

       

        privateView findWindow(int hashCode) {

            if(hashCode == -1) {

               View window = null;

               mWindowsLock.readLock().lock();

               try {

                   window = mFocusedWindow;

               } finally {

                   mWindowsLock.readLock().unlock();

               }

               return window;

            }

 

           

           mWindowsLock.readLock().lock();

            try {

               for (Entry<View, String> entry : mWindows.entrySet()) {

                   if (System.identityHashCode(entry.getKey()) == hashCode) {

                        return entry.getKey();

                   }

               }

            } finally {

               mWindowsLock.readLock().unlock();

            }

 

           return null;

        }

       

        privateboolean listWindows(Socket client) {

           boolean result = true;

           BufferedWriter out = null;

 

            try{

               mWindowsLock.readLock().lock();

 

               OutputStream clientStream = client.getOutputStream();

               out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 *1024);

 

               for (Entry<View, String> entry : mWindows.entrySet()) {

                   out.write(Integer.toHexString(System.identityHashCode(entry.getKey())));

                   out.write(' ');

                   out.append(entry.getValue());

                   out.write('\n');

               }

 

               out.write("DONE.\n");

               out.flush();

            }catch (Exception e) {

               result = false;

            }finally {

               mWindowsLock.readLock().unlock();

 

               if (out != null) {

                   try {

                        out.close();

                   } catch (IOException e) {

                        result = false;

                   }

               }

            }

 

           return result;

        }

        

        privateboolean getFocusedWindow(Socket client) {

           boolean result = true;

           String focusName = null;

 

           BufferedWriter out = null;

            try{

               OutputStream clientStream = client.getOutputStream();

               out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 *1024);

 

               View focusedWindow = null;

               

               mFocusLock.readLock().lock();

               try {

                   focusedWindow = mFocusedWindow;

               } finally {

                   mFocusLock.readLock().unlock();

               }

 

               if (focusedWindow != null) {

                   mWindowsLock.readLock().lock();

                   try {

                        focusName =mWindows.get(mFocusedWindow);

                   } finally {

                       mWindowsLock.readLock().unlock();

                   }

 

                   out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));

                   out.write(' ');

                   out.append(focusName);

               }

               out.write('\n');

               out.flush();

            }catch (Exception e) {

               result = false;

            }finally {

               if (out != null) {

                   try {

                        out.close();

                   } catch (IOException e) {

                        result = false;

                   }

               }

            }

 

           return result;

        }

 

        publicvoid windowsChanged() {

           synchronized (mLock) {

               mNeedWindowListUpdate = true;

               mLock.notifyAll();

            }

        }

 

        publicvoid focusChanged() {

           synchronized (mLock) {

               mNeedFocusedWindowUpdate = true;

               mLock.notifyAll();

            }

        }

 

        privateboolean windowManagerAutolistLoop() {

           addWindowListener(this);

           BufferedWriter out = null;

            try{

               out = new BufferedWriter(newOutputStreamWriter(mClient.getOutputStream()));

               while (!Thread.interrupted()) {

                   boolean needWindowListUpdate = false;

                   boolean needFocusedWindowUpdate = false;

                   synchronized (mLock) {

                        while(!mNeedWindowListUpdate && !mNeedFocusedWindowUpdate) {

                            mLock.wait();

                        }

                       if (mNeedWindowListUpdate) {

                           mNeedWindowListUpdate = false;

                           needWindowListUpdate = true;

                        }

                        if(mNeedFocusedWindowUpdate) {

                            mNeedFocusedWindowUpdate = false;

                           needFocusedWindowUpdate = true;

                        }

                   }

                   if (needWindowListUpdate) {

                        out.write("LISTUPDATE\n");

                        out.flush();

                   }

                   if (needFocusedWindowUpdate) {

                        out.write("FOCUSUPDATE\n");

                        out.flush();

                   }

               }

            }catch (Exception e) {

               Log.w(LOG_TAG, "Connection error: ", e);

            }finally {

               if (out != null) {

                   try {

                        out.close();

                   } catch (IOException e) {

                       // Ignore

                   }

               }

               removeWindowListener(this);

            }

           return true;

        }

    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值