package com.glview.thread; import android.os.Build; import android.os.Process; import android.os.StrictMode; import android.os.StrictMode.ThreadPolicy; import android.util.Log; /** * GLView的MainLooper,使用该线程{@link GLHandlerThread} * 通过{@link #getGLLooper()} 取得GLThread主线程 * @author lijing.lj */ final class GLLooper { private final static String TAG = "GLLooper"; private static Looper sGLMainLooper; private static GLHandlerThread sGLMainThread; /** * 线程允许的异常次数 * 0表示不允许出现任何异常,否则直接crash * @see GLHandlerThread#intoLoop() */ private final static int MAX_LOOP_EXCEPTION_ALLOWED = 0; private static void ensureGLThread() { if (sGLMainThread == null || !sGLMainThread.isAlive()) { sGLMainThread = new GLHandlerThread(true); sGLMainThread.start(); sGLMainLooper = sGLMainThread.getLooper(); Watchdog.getInstance().addThread(sGLMainLooper, new Handler(sGLMainLooper), "GLMainThread"); } } /** * MainLooper * @return */ public synchronized static Looper getGLMainLooper() { ensureGLThread(); return sGLMainLooper; // return Looper.getMainLooper(); } static class GLHandlerThread extends Thread { boolean mMainLooper; Looper mLooper; public GLHandlerThread() { this(false); } public GLHandlerThread(boolean mainLooper) { mMainLooper = mainLooper; } @Override public void run() { setName("GLThread " + getId()); Log.i(TAG, "starting tid=" + getId()); init(); if (mMainLooper) { // 主线程,调用prepare(false),线程不允许被quit /*try { Log.i(TAG, "Try to prepare the looper with declaredMethod 'private static void android.os.Looper.prepare(boolean)' to set quitAllowed=false"); Method m = Looper.class.getDeclaredMethod("prepare", boolean.class); m.setAccessible(true); m.invoke(null, false); m.setAccessible(false); } catch(Exception e) { Log.w(TAG, "Reflection failed, use public prepare", e); }*/ Looper.prepareMainLooper(); } if (Looper.myLooper() == null) { Looper.prepare(); } synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } intoLoop(); } void init() { Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY); // disable network access in main thread if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { StrictMode.setThreadPolicy(new ThreadPolicy.Builder().detectNetwork().penaltyDeathOnNetwork().build()); } } void intoLoop() { int exceptionCount = 0; while (true) { try { Looper.loop(); } /*catch (NetworkOnMainThreadException e) { Log.w(TAG, "GLHandlerThread catch NetworkOnMainThreadException, crash the process, fix it", e); throw e; } */catch(Throwable e) { Log.w(TAG, "GLHandlerThread catch some exception", e); if (++ exceptionCount > MAX_LOOP_EXCEPTION_ALLOWED) { Log.w(TAG, "Beyond the max allowed count, crash the process. exceptionCount:" + exceptionCount + ", MAX_LOOP_EXCEPTION_ALLOWED:" + MAX_LOOP_EXCEPTION_ALLOWED); throw new RuntimeException(e); } // maybe we can continue the loop Log.w(TAG, "Maybe we can continue the loop. exceptionCount:" + exceptionCount + ", MAX_LOOP_EXCEPTION_ALLOWED:" + MAX_LOOP_EXCEPTION_ALLOWED); continue; } // no exception, safe quit return; } } /** * This method returns the Looper associated with this thread. If this thread not been started * or for any reason is isAlive() returns false, this method will return null. If this thread * has been started, this method will block until the looper has been initialized. * @return The looper. */ public Looper getLooper() { if (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; } } }