blob: f9ee2f44a2294ff54b768bc2d3b7cb00683e2593 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.weex.common;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.HandlerThread;
import android.os.Message;
import org.apache.weex.WXEnvironment;
import org.apache.weex.WXSDKInstance;
import org.apache.weex.utils.WXLogUtils;
import org.apache.weex.utils.tools.LogDetail;
import java.lang.ref.WeakReference;
import org.apache.weex.utils.tools.TimeCalculator;
/**
* Thread used in weex
*/
public class WXThread extends HandlerThread {
private Handler mHandler;
static class SafeRunnable implements Runnable {
static final String TAG = "SafeRunnable";
private LogDetail mTimelineLog = null;
private WeakReference<WXSDKInstance> mInstance;
final Runnable mTask;
SafeRunnable(Runnable task){
this(task,null);
}
SafeRunnable(Runnable task, String taskName){
this(task,null, taskName);
}
SafeRunnable(Runnable runnable, WXSDKInstance instance, String taskName) {
mTask = runnable;
if(taskName != null) {
mTimelineLog = new LogDetail();
mTimelineLog.info.platform = TimeCalculator.PLATFORM_ANDROID;
mTimelineLog.name(taskName);
mInstance = new WeakReference<>(instance);
}
}
@Override
public void run() {
try {
if(mTask != null) {
if (mTimelineLog != null)
mTimelineLog.taskStart();
mTask.run();
if (mTimelineLog != null)
mTimelineLog.taskEnd();
}
}catch (Throwable e){
//catch everything may throw from exection.
if(WXEnvironment.isApkDebugable()){
WXLogUtils.e(TAG,"SafeRunnable run throw expection:"+e.getMessage());
throw e;
}
WXLogUtils.w(TAG, e);
}
if (mTimelineLog != null) {
if(mInstance != null) {
WXSDKInstance wxsdkInstance = mInstance.get();
if(wxsdkInstance != null) {
wxsdkInstance.mTimeCalculator.addLog(mTimelineLog);
}
}
}
}
}
static class SafeCallback implements Callback {
static final String TAG = "SafeCallback";
final Callback mCallback;
SafeCallback(Callback cb){
mCallback = cb;
}
@Override
public boolean handleMessage(Message msg) {
boolean result = false;
try{
if(mCallback != null){
result = mCallback.handleMessage(msg);
}
}catch (Throwable e){
//catch everything may throw from exection.
if(WXEnvironment.isApkDebugable()){
WXLogUtils.e(TAG,"SafeCallback handleMessage throw expection:"+e.getMessage());
throw e;
}
}
return result;
}
}
/**
* Secure Runnable to prevent throw during execution.
* NOTE: DO NOT use this method to wrap runnable that may be removed by {@link Handler#removeCallbacks(Runnable)}
* @param runnable
* @return
*/
public static Runnable secure(Runnable runnable){
return secure(runnable, null, null);
}
public static Runnable secure(Runnable runnable, WXSDKInstance instance, String runnableName){
if(runnable == null || runnable instanceof SafeRunnable){
return runnable;
}
return new SafeRunnable(runnable,instance, runnableName);
}
public static Callback secure(Callback callback){
if(callback == null || callback instanceof SafeCallback){
return callback;
}
return new SafeCallback(callback);
}
/**
* @param name name of thread
*/
public WXThread(String name) {
super(name);
start();
mHandler = new Handler(getLooper());
}
public WXThread(String name, Callback callback) {
super(name);
start();
mHandler = new Handler(getLooper(), secure(callback));
}
/**
* @param name name of thread
* @param priority The priority to run the thread at. The value supplied must be from
* {@link android.os.Process} and not from java.lang.Thread.
*/
public WXThread(String name, int priority, Callback callback) {
super(name, priority);
start();
mHandler = new Handler(getLooper(), secure(callback));
}
/**
* @param name name of thread
* @param priority The priority to run the thread at. The value supplied must be from
* {@link android.os.Process} and not from java.lang.Thread.
*/
public WXThread(String name, int priority) {
super(name, priority);
start();
mHandler = new Handler(getLooper());
}
public Handler getHandler() {
return mHandler;
}
public boolean isWXThreadAlive() {
return (mHandler != null && getLooper() != null && isAlive());
}
@Override
public boolean quit() {
if (mHandler != null) {
mHandler.removeCallbacksAndMessages(null);
}
return super.quit();
}
}