这是所有回调方法的替代解决方案,这些方法可能都受到具有活动周期的相同未定义事件顺序行为的影响。除非您要检查用于确定源触发器和控制实现的每个回调的所有 android 代码,并希望代码库将来不会更改,否则真的可以说明回调之间的事件顺序和活动生命周期事件可以得到保证。
现在,出于开发目的,这些顺序交互通常可以称为未定义行为。
所以最好总是正确处理这种未定义的行为,这样
通过确保订单是已定义的行为,这从一开始就不会成为问题。
例如,我的 Sony Xperia 在睡眠时循环我当前的应用程序,通过销毁应用程序然后重新启动它并将其置于暂停状态,信不信由你。
google 在他们的 SDK 中提供了多少事件排序行为测试作为宿主环境实现的特殊测试构建我不知道,但他们肯定需要努力确保事件排序行为都被锁定对此事严格。
https://code.google.com/p/android/issues/detail?id=214171&sort=-opened&colspec=ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20Opened
导入android.util.Log;
导入 android.util.SparseArray;
/**
* 由 woliver 于 2016/06/24 创建。
*
* Android 主机环境,规定了 OnCreate、onStart、onResume、onPause、onStop、onDestory 的 Activity 生命周期,
* 我们需要释放内存和句柄以供其他应用程序使用。
* 恢复时,我们有时需要重新绑定并激活这些项目与其他对象。
* 通常,这些其他对象提供来自宿主环境的回调方法,这些方法提供
* 一个 onCreated 和 onDestroy,其中我们只能从 OnCreated 和松散绑定到这个对象
* out 绑定 onDestory。
* 这些类型的回调方法,运行时间是我们主机环境的控制器
* 并且它们不能保证活动生命周期的行为/执行顺序和这些回调方法
* 保持一致。
*出于开发目的,交互和执行顺序在技术上可以称为未定义
* 这取决于主机实现实施者,三星、索尼、HTC。
*
* 请参阅以下开发者文档:https://developer.android.com/reference/android/app/Activity.html
* 引用:
* 如果一个活动被另一个活动完全遮挡,它就会停止。它仍然保留所有状态
* 和会员信息,但是,它不再对用户可见,因此它的窗口是
*隐藏,当其他地方需要内存时,它通常会被系统杀死。
* EndQuato:
*
* 如果活动没有隐藏,那么主机会调用任何回调
* 系统,不会被调用,如 OnCreate 和 OnDestory 方法接口 SurfaceView 回调。
* 这意味着您将不得不停止已绑定到 SurfaceView 的对象,例如相机
* 暂停并且永远不会重新绑定对象,因为永远不会调用 OnCreate 回调。
*
*/
public abstract class WaitAllActiveExecuter<Size>
{
private SparseArray<Boolean> mReferancesState = null;
// Use a dictionary and not just a counter, as hosted code
// environment implementer may make a mistake and then may double executes things.
private int mAllActiveCount = 0;
private String mContextStr;
public WaitAllActiveExecuter(String contextStr, int... identifiers)
{
mReferancesState = new SparseArray<Boolean>(identifiers.length);
mContextStr = contextStr;
for (int i = 0; i < identifiers.length; i++)
mReferancesState.put(identifiers[i], false);
}
public void ActiveState(int identifier)
{
Boolean state = mReferancesState.get(identifier);
if (state == null)
{
// Typically panic here referance was not registered here.
throw new IllegalStateException(mContextStr + "ActiveState: Identifier not found '" + identifier + "'");
}
else if(state == false){
mReferancesState.put(identifier, true);
mAllActiveCount++;
if (mAllActiveCount == mReferancesState.size())
RunActive();
}
else
{
Log.e(mContextStr, "ActivateState: called to many times for identifier '" + identifier + "'");
// Typically panic here and output a log message.
}
}
public void DeactiveState(int identifier)
{
Boolean state = mReferancesState.get(identifier);
if (state == null)
{
// Typically panic here referance was not registered here.
throw new IllegalStateException(mContextStr + "DeActiveState: Identifier not found '" + identifier + "'");
}
else if(state == true){
if (mAllActiveCount == mReferancesState.size())
RunDeActive();
mReferancesState.put(identifier, false);
mAllActiveCount--;
}
else
{
Log.e(mContextStr,"DeActiveState: State called to many times for identifier'" + identifier + "'");
// Typically panic here and output a log message.
}
}
private void RunActive()
{
Log.v(mContextStr, "Executing Activate");
ExecuterActive();
}
private void RunDeActive()
{
Log.v(mContextStr, "Executing DeActivate");
ExecuterDeActive();
}
abstract public void ExecuterActive();
abstract public void ExecuterDeActive();
}
类的实现和使用示例,处理或未定义的android宿主环境行为
实施者。
private final int mBCTSV_SurfaceViewIdentifier = 1;
private final int mBCTSV_CameraIdentifier = 2;
private WaitAllActiveExecuter mBindCameraToSurfaceView =
new WaitAllActiveExecuter("BindCameraToSurfaceViewe", new int[]{mBCTSV_SurfaceViewIdentifier, mBCTSV_CameraIdentifier})
{
@Override
public void ExecuterActive() {
// Open a handle to the camera, if not open yet and the SurfaceView is already intialized.
if (mCamera == null)
{
mCamera = Camera.open(mCameraIDUsed);
if (mCamera == null)
throw new RuntimeException("Camera could not open");
// Look at reducing the calls in the following two methods, some this is unessary.
setDefaultCameraParameters(mCamera);
setPreviewSizesForCameraFromSurfaceHolder(getSurfaceHolderForCameraPreview());
}
// Bind the Camera to the SurfaceView.
try {
mCamera.startPreview();
mCamera.setPreviewDisplay(getSurfaceHolderForCameraPreview());
} catch (IOException e) {
e.printStackTrace();
ExecuterDeActive();
throw new RuntimeException("Camera preview could not be set");
}
}
@Override
public void ExecuterDeActive() {
if ( mCamera != null )
{
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
};
@Override
protected void onPause() {
mBindCameraToSurfaceView.DeactiveState(mBCTSV_CameraIdentifier);
Log.v(LOG_TAG, "Activity Paused - After Super");
}
@Override
public void onResume() {
mBindCameraToSurfaceView.ActiveState(mBCTSV_CameraIdentifier);
}
private class SurfaceHolderCallback implements SurfaceHolder.Callback
{
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.v(LOG_TAG, "Surface Changed");
}
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.v(LOG_TAG, "Surface Created");
mBindCameraToSurfaceView.ActiveState(mBCTSV_SurfaceViewIdentifier);
}
public void surfaceDestroyed(SurfaceHolder arg0) {
Log.v(LOG_TAG, "Surface Destoryed");
mBindCameraToSurfaceView.DeactiveState(mBCTSV_SurfaceViewIdentifier);
}
}