Jetpack学习-1-Lifecycle+Activity源码分析

2023-10-29

解耦是软件开发亘古不变的追求,而Lifecycle正是这一名言的体现。

Android开发过程中,有些功能不可避免与页面的生命周期关联,LifeCycle作为Jetpack中具有生命周期感知姓的组件,通过感知activity/fragment/service/application的生命周期状态而做不同操作,功能与页面完成解耦,避免发生内存泄露。

本文我们将记录Lifecycle在Activity中的使用,以及源码分析。

Lifecycle在Activity上的使用

1,我们首先创建一个对象,并实现LifecycleObserver,这个对象就具有感知生命周期的能力。

package com.sun.lifecycle;

import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;

import com.sun.common_library.util.LogUtil;

/**
 * 具有感知Activity/fragment/service/application生命周期的能力
 * 说白了就是创建了一个观察者,只要它看向哪个对象,就能知道那个对象的生命周期到那了
 * 这样就能选择性的在不同的生命周期做不同的操作,从而和activity/fragment/service/application实现解耦
 */
public class CustomObserver implements LifecycleObserver {

    private final String TAG = "CustomObserver";

    @OnLifecycleEvent(value = Lifecycle.Event.ON_RESUME)
    public void onResume() {
        LogUtil.e(TAG, "Observer ON_RESUME");
        //TODO 做些操作
    }

    @OnLifecycleEvent(value = Lifecycle.Event.ON_START)
    public void onStart() {
        LogUtil.e(TAG, "Observer ON_START");
        //TODO 做些操作
    }

    @OnLifecycleEvent(value = Lifecycle.Event.ON_CREATE)
    public void onCreate() {
        LogUtil.e(TAG, "Observer ON_CREATE");
        //TODO 做些操作
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void onPause() {
        LogUtil.e(TAG, "Observer ON_PAUSE");
        //TODO 做些操作
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void onDestory() {
        LogUtil.e(TAG, "Observer ON_DESTROY");
        //TODO 做些操作
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void onStop() {
        LogUtil.e(TAG, "Observer ON_STOP");
        //TODO 做些操作
    }

//    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
//    public void onAny() {
//        LogUtil.e(TAG, "Observer ON_ANY  只要上面有调用,此方法也会调用");
//    }

}

2,我们在activity的生命周期方法打日志留痕,同时添加观察者

 getLifecycle().addObserver(new CustomObserver());

3,执行页面进去及出退操作,得到日志

进入activity

MainActivity: onCreate
CustomObserver: Observer ON_CREATE
MainActivity: onStart
CustomObserver: Observer ON_START
MainActivity: onResume
CustomObserver: Observer ON_RESUME


退出activity
CustomObserver: Observer ON_PAUSE
MainActivity: onPause
CustomObserver: Observer ON_STOP
MainActivity: onStop
CustomObserver: Observer ON_DESTROY
MainActivity: onDestroy

源码分析

一言以蔽之,就是activity和操作类组成观察者模式,activity生命周期变化会通知到操作类,下面具体源码分析。

1,androidx对原始activity进行了二次封装,在androidx.activity.ComponentActivity已经实现了LifecycleOwner接口,从而使activity变成了被观察者

2,androidx.activity.ComponentActivity

 @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mSavedStateRegistryController.performRestore(savedInstanceState);
        ReportFragment.injectIfNeededIn(this);//通过创建一个空白fragment并交给它处理生命周期变化的任务
        if (mContentLayoutId != 0) {
            setContentView(mContentLayoutId);
        }
    }

3,androidx.lifecycle.ReportFragment

public class ReportFragment extends Fragment {
    //创建fragment的方法
    public static void injectIfNeededIn(Activity activity) {

        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();

            manager.executePendingTransactions();
        }
    }
    //调遣事件ON_CREATE
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        dispatch(Lifecycle.Event.ON_CREATE);
    }
    //调遣事件ON_START
    @Override
    public void onStart() {
        super.onStart();
        dispatch(Lifecycle.Event.ON_START);
    }
    //调遣事件ON_RESUME
    @Override
    public void onResume() {
        super.onResume();
        dispatchResume(mProcessListener);
        dispatch(Lifecycle.Event.ON_RESUME);
    }
    //调遣事件ON_PAUSE
    @Override
    public void onPause() {
        super.onPause();
        dispatch(Lifecycle.Event.ON_PAUSE);
    }
    //调遣事件ON_STOP
    @Override
    public void onStop() {
        super.onStop();
        dispatch(Lifecycle.Event.ON_STOP);
    }
    //调遣事件ON_DESTROY
    @Override
    public void onDestroy() {
        super.onDestroy();
        dispatch(Lifecycle.Event.ON_DESTROY);
        mProcessListener = null;
    }

    private void dispatch(Lifecycle.Event event) {
        Activity activity = getActivity();
        if (activity instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
            return;
        }

        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);//再把具体处理放在被观察者的具体实现上
            }
        }
    } 
}

分析LifecycleRegistry之前,我们需要先看下LifeCycle源码,它是生命周期被观察者的基类,定义了 生命周期被观察者 的行为规范。

package androidx.lifecycle;

import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;

import java.util.concurrent.atomic.AtomicReference;

public abstract class Lifecycle {

    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    @NonNull
    AtomicReference<Object> mInternalScopeRef = new AtomicReference<>();

    @MainThread
    public abstract void addObserver(@NonNull LifecycleObserver observer);

    @MainThread
    public abstract void removeObserver(@NonNull LifecycleObserver observer);

    @MainThread
    @NonNull
    public abstract State getCurrentState();

    @SuppressWarnings("WeakerAccess")
    public enum Event {
        ON_CREATE,
        ON_START,
        ON_RESUME,
        ON_PAUSE,
        ON_STOP,
        ON_DESTROY,
        ON_ANY
    }

    /**
     * Lifecycle states. You can consider the states as the nodes in a graph and
     * {@link Event}s as the edges between these nodes.
     */
    @SuppressWarnings("WeakerAccess")
    public enum State {
        DESTROYED,
        INITIALIZED,
        CREATED,
        STARTED,
        RESUMED;
        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0;
        }
    }
}

Lifecycle是一个抽象类,定义了添加/移除观察者的抽象方法,通知定义了事件枚举类和状态枚举类。

而LifecycleRegistry是Lifecycle的具体继承者,LifecycleRegistry在类中实现增加/删除观察者,关键还有对观察者发送状态变化的接收方法,具体如下。

package androidx.lifecycle;


public class LifecycleRegistry extends Lifecycle {


    private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
            new FastSafeIterableMap<>();

    private State mState;

    private final WeakReference<LifecycleOwner> mLifecycleOwner;

    public LifecycleRegistry(@NonNull LifecycleOwner provider) {
        mLifecycleOwner = new WeakReference<>(provider);
        mState = INITIALIZED;
    }
    //添加观察者
    @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);//把观察者封装成ObserverWithState
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
        ...
    }


    //删除观察者
    @Override
    public void removeObserver(@NonNull LifecycleObserver observer) {
       mObserverMap.remove(observer);
    }

    //这里对接上了ReportFragment的代码-dispatch(Lifecycle.Event)-->((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
    public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        State next = getStateAfter(event);
        moveToState(next);
    }

    //字面意思 移动状态
    private void moveToState(State next) {
        ...
        mHandlingEvent = true;
        sync();//状态同步  准备把状态同步给观察者
        mHandlingEvent = false;
    }

 //通知状态 到这里了
    private void sync() {
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already"
                    + "garbage collected. It is too late to change lifecycle state.");
        }
        while (!isSynced()) {
            mNewEventOccurred = false;
            // no need to check eldest for nullability, because isSynced does it for us.
            if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
                backwardPass(lifecycleOwner);//根据状态选择执行
            }
            Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
            if (!mNewEventOccurred && newest != null
                    && mState.compareTo(newest.getValue().mState) > 0) {
                forwardPass(lifecycleOwner);//根据状态选择执行
            }
        }
        mNewEventOccurred = false;
    }
    //对保存在map中的观察者进行逐一通知
    private void forwardPass(LifecycleOwner lifecycleOwner) {
        Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
                mObserverMap.iteratorWithAdditions();
        while (ascendingIterator.hasNext() && !mNewEventOccurred) {
            Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                pushParentState(observer.mState);
                observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
                popParentState();
            }
        }
    }



    //对保存在map中的观察者进行逐一通知
    private void backwardPass(LifecycleOwner lifecycleOwner) {
        Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
                mObserverMap.descendingIterator();
        while (descendingIterator.hasNext() && !mNewEventOccurred) {
            Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                Event event = downEvent(observer.mState);
                pushParentState(getStateAfter(event));
                observer.dispatchEvent(lifecycleOwner, event);//执行通知事件的方法
                popParentState();
            }
        }
    }

    static class ObserverWithState {
        State mState;
        LifecycleEventObserver mLifecycleObserver;

        ObserverWithState(LifecycleObserver observer, State initialState) {
            mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);//具体的实现类在这里面
            mState = initialState;
        }

        void dispatchEvent(LifecycleOwner owner, Event event) {//这里是执行通知具体操作的方法
            State newState = getStateAfter(event);
            mState = min(mState, newState);
            mLifecycleObserver.onStateChanged(owner, event);//事件操作,下面是实际的操作流程,由上面的Lifecycling.lifecycleEventObserver
            mState = newState;
        }
    }
}

分析Lifecycling中的lifecycleEventObserver()

@NonNull
    static LifecycleEventObserver lifecycleEventObserver(Object object) {//我们的观察者实现的是 LifecycleObserver
        boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver;//false
        boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver;  //false
        if (isLifecycleEventObserver && isFullLifecycleObserver) {
            return new FullLifecycleObserverAdapter((FullLifecycleObserver) object,
                    (LifecycleEventObserver) object);
        }
        if (isFullLifecycleObserver) {
            return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, null);
        }

        if (isLifecycleEventObserver) {
            return (LifecycleEventObserver) object;
        }

        final Class<?> klass = object.getClass();
        int type = getObserverConstructorType(klass);
        if (type == GENERATED_CALLBACK) {
            List<Constructor<? extends GeneratedAdapter>> constructors =
                    sClassToAdapters.get(klass);
            if (constructors.size() == 1) {
                GeneratedAdapter generatedAdapter = createGeneratedAdapter(
                        constructors.get(0), object);
                return new SingleGeneratedAdapterObserver(generatedAdapter);
            }
            GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()];
            for (int i = 0; i < constructors.size(); i++) {
                adapters[i] = createGeneratedAdapter(constructors.get(i), object);
            }
            return new CompositeGeneratedAdaptersObserver(adapters);
        }
        return new ReflectiveGenericLifecycleObserver(object);//最终是这句话执行了
    }

ReflectiveGenericLifecycleObserver类分析

package androidx.lifecycle;


class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver {
    private final Object mWrapped;
    private final CallbackInfo mInfo;

    ReflectiveGenericLifecycleObserver(Object wrapped) {
        mWrapped = wrapped;
        mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());//转到ClassesInfoCache中获取CallbackInfo类,里面包含所有带Lifecycle.Event注解的方法
    }

    @Override
    public void onStateChanged(LifecycleOwner source, Event event) {//LifecycleRegistry类中类ObserverWithState中的dispatchEvent()
        mInfo.invokeCallbacks(source, event, mWrapped);//最终执行的方法
    }
}

ClassesInfoCache部分关键方法的梳理

//androidx.lifecycle.ClassesInfoCache


 CallbackInfo getInfo(Class klass) {
        CallbackInfo existing = mCallbackMap.get(klass);
        if (existing != null) {
            return existing;
        }
        existing = createInfo(klass, null);//关键代码
        return existing;
    }


 private CallbackInfo createInfo(Class klass, @Nullable Method[] declaredMethods) {
        Class superclass = klass.getSuperclass();
        Map<MethodReference, Lifecycle.Event> handlerToEvent = new HashMap<>();
        if (superclass != null) {
            CallbackInfo superInfo = getInfo(superclass);
            if (superInfo != null) {
                handlerToEvent.putAll(superInfo.mHandlerToEvent);
            }
        }

        Class[] interfaces = klass.getInterfaces();
        for (Class intrfc : interfaces) {
            for (Map.Entry<MethodReference, Lifecycle.Event> entry : getInfo(
                    intrfc).mHandlerToEvent.entrySet()) {
                verifyAndPutHandler(handlerToEvent, entry.getKey(), entry.getValue(), klass);
            }
        }

        Method[] methods = declaredMethods != null ? declaredMethods : getDeclaredMethods(klass);
        boolean hasLifecycleMethods = false;
        for (Method method : methods) {//遍历所有方法,并把带OnLifecycleEvent的方法搞出来
            OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);
            if (annotation == null) {
                continue;
            }
            hasLifecycleMethods = true;
            Class<?>[] params = method.getParameterTypes();
            int callType = CALL_TYPE_NO_ARG;
            if (params.length > 0) {
                callType = CALL_TYPE_PROVIDER;
                if (!params[0].isAssignableFrom(LifecycleOwner.class)) {
                    throw new IllegalArgumentException(
                            "invalid parameter type. Must be one and instanceof LifecycleOwner");
                }
            }
            Lifecycle.Event event = annotation.value();

            if (params.length > 1) {
                callType = CALL_TYPE_PROVIDER_WITH_EVENT;
                if (!params[1].isAssignableFrom(Lifecycle.Event.class)) {
                    throw new IllegalArgumentException(
                            "invalid parameter type. second arg must be an event");
                }
                if (event != Lifecycle.Event.ON_ANY) {
                    throw new IllegalArgumentException(
                            "Second arg is supported only for ON_ANY value");
                }
            }
            if (params.length > 2) {
                throw new IllegalArgumentException("cannot have more than 2 params");
            }
            MethodReference methodReference = new MethodReference(callType, method);//又把观察者中的注解方法封装一下
            verifyAndPutHandler(handlerToEvent, methodReference, event, klass);//然后又放到一个map中
        }
        CallbackInfo info = new CallbackInfo(handlerToEvent);
        mCallbackMap.put(klass, info);
        mHasLifecycleMethods.put(klass, hasLifecycleMethods);
        return info;
    }

        //ReflectiveGenericLifecycleObserver类的onStateChanged具体执行方法
        void invokeCallbacks(LifecycleOwner source, Lifecycle.Event event, Object target) {
            invokeMethodsForEvent(mEventToHandlers.get(event), source, event, target);
            invokeMethodsForEvent(mEventToHandlers.get(Lifecycle.Event.ON_ANY), source, event,
                    target);
        }

        private static void invokeMethodsForEvent(List<MethodReference> handlers,
                LifecycleOwner source, Lifecycle.Event event, Object mWrapped) {
            if (handlers != null) {
                for (int i = handlers.size() - 1; i >= 0; i--) {
                    handlers.get(i).invokeCallback(source, event, mWrapped);//终于快到尾巴上了
                }
            }
        }
    //通过invoke执行观察者中被生命周期关联的方法
  void invokeCallback(LifecycleOwner source, Lifecycle.Event event, Object target) {
            //noinspection TryWithIdenticalCatches
            try {
                switch (mCallType) {
                    case CALL_TYPE_NO_ARG:
                        mMethod.invoke(target);
                        break;
                    case CALL_TYPE_PROVIDER:
                        mMethod.invoke(target, source);
                        break;
                    case CALL_TYPE_PROVIDER_WITH_EVENT:
                        mMethod.invoke(target, source, event);
                        break;
                }
            } catch (InvocationTargetException e) {
                throw new RuntimeException("Failed to call observer method", e.getCause());
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }

Android-Jetpack代码位置:github

Lifecycle在activity的整体流程梳理,大致如下:

总结:Lifecycle在activity中使用可以说是相当简单,注册-->空页面感知-->通知被观察者-->反射观察者包含OnLifecycleEvent的方法->invoke触发,

完美实现业务逻辑和activity的生命周期方法解耦。

下一篇文章将分析Lifecycle在Service和Application中的使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Jetpack学习-1-Lifecycle+Activity源码分析 的相关文章

  • 将数据从服务传递到活动

    我有自行运行的服务 服务自动启动 我有活动 在此 Activity 按钮中启动该方法DoIt Button setOnClickListener new OnClickListener public void onClick View v
  • 使用 JSONArray 还是普通数组来存储/读取数据更有效?

    我正在使用一个连接到PHP MySQL返回所有内容的服务器JSON格式 例如 用户列表作为JSONArray of JSONObject 每个对象都包含单个用户的信息 姓名 位置 电话号码等 处理这种格式的信息时 将所有内容保留在其中会更有
  • 如何在 Android 中更改 Drawable 的颜色?

    我正在开发一个 Android 应用程序 并且我有一个从源图像加载的可绘制对象 在此图像上 我想将所有白色像素转换为不同的颜色 例如蓝色 然后缓存生成的 Drawable 对象 以便稍后使用它 举例来说 假设我有一个 20x20 PNG 文
  • 如何在应用程序关闭时在 Android 通知中显示操作按钮?

    我有一个安卓应用程序 对于通知 我们必须显示一些操作按钮 当应用程序打开时 我们可以自由地构建通知并显示操作按钮 但是当应用程序关闭时 通知会在 Android 的通知托盘中收到 应用程序开发人员无法控制构建用户界面和操作按钮 我们现在如何
  • 在 ChromeO 上安装未知来源的 apk

    我今天早上更新了我的 Chromebook Asus Flip 以获取 Play 商店 我的 Chromebook 安装了 M53dev 通道版本 它运作良好 我可以安装并运行从 Play 商店下载的 Android 应用程序 我想测试我的
  • Android 图表[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在开发一个项目 其中有一些图表 图形 刻度图 烛台图和范围图 但问题是 没有该图表的库 我有烛台图的
  • 覆盖 Android 中的电源按钮

    我正在开发一个应用程序 其中我需要在按下电源按钮时执行一个操作 但不幸的是我无法处理按下电源按钮时的操作 我尝试使用 onKeyDown 和dispatchKeyEvent 方法 但似乎没有任何效果 任何人都可以建议我解决这个问题的任何其他
  • ADB TCPIP 连接问题

    我有两台 Galaxy S3 其中一个已扎根 另一个则未扎根 因此 当我尝试通过本地网络连接它们时 计算机可以看到已root的计算机 但是正常的就卡在tcpip这一步了 所以 我写 adb tcpip 5555 It says restar
  • HMS 核心地图套件在我的 Android 应用程序上根本无法工作

    我正在尝试在我的应用程序中使用华为 HMS 地图套件 我对整体地图很陌生 无论是来自谷歌还是华为 我按照文档中的教程以及华为提供的代码实验室中的说明进行操作 并将我的代码在一起 但是当我运行地图活动时 什么也没有出现 我得到的只是一个空白活
  • ExpandableListview OnGroupClickListener 未触发

    我正在关注这个 以编程方式折叠 ExpandableListView 中的组 https stackoverflow com questions 4314777 programmatically collapse a group in ex
  • 使用 Play Integrity API 时,Firebase 电话身份验证会出现缺少客户端标识符错误

    使用 Firebase 电话身份验证注册 登录时 身份验证流程始终会启动 reCAPTCHA 流程 并在返回应用程序后发出missing client identifier error 我的设置之前适用于设备验证 安全网络 API 除了我的
  • Android:GestureDetector 无法与选项卡(TabActivity、Tabwidget)一起工作(gestureDetector.onTouchEvent(event) 始终为 false)

    我已经用不同的子活动实现了 TabActivity intent new Intent setClass this MyChildTabActiviy class Initialize a TabSpec for each tab and
  • onTaskRemoved() 在华为和小米设备中没有被调用

    我一直在使用onTaskRemoved 服务中的方法 用于检测应用程序何时通过滑动从设备最近列表中删除 我执行一些日志记录和发生这种情况时需要执行的一些其他操作 它工作完美 然后我在运行Android 6 0的华为设备上检查了这个方法 该方
  • 受信任的网络活动 - 地址栏不隐藏(Android 72 的 Chrome)

    我已经关注了this https developers google com web updates 2017 10 using twa了解如何使用受信任的 Web 活动的指南 一切正常 但地址栏仍然出现 一开始我认为这是因为当应用程序正在
  • 如何在android中通过蓝牙向配对设备发送短信?

    在我的应用程序中 我想通过蓝牙发送和接收短信 我可以在列表视图中看到配对设备名称和地址的列表 但是当我尝试向配对设备发送文本时 什么也没有发生 在其他设备中没有收到文本 这是我向配对设备发送消息的代码 private void sendDa
  • 如何更改操作栏背景和文本颜色

    我正在使用本教程中的导航抽屉 http www androidhive info 2013 11 android sliding menu using navigation drawer http www androidhive info
  • 丢失应用程序的密钥库文件(但已启用 Google Play 应用程序签名)

    我已经失去了原来的keystore用于签署我的应用程序的文件 我的应用启用了 Google Play 应用签名 如果我联系 Google 支持人员 是否可以重置密钥 以便我可以继续上传到此包 我希望我可以做到这一点 因为应用程序签名已启用
  • 检查应用程序是否在 Android Market 上可用

    给定 Android 应用程序 ID 包名称 如何以编程方式检查该应用程序是否在 Android Market 上可用 例如 com rovio angrybirds 可用 而 com random app ibuilt 不可用 我计划从
  • 将对象从手机共享到 Android Wear

    我创建了一个应用程序 在此应用程序中 您拥有包含 2 个字符串 姓名和年龄 和一个位图 头像 的对象 所有内容都保存到 sqlite 数据库中 现在我希望可以在我的智能手表上访问这些对象 所以我想实现的是你可以去启动 启动应用程序并向左和向
  • LifeCycleAware Fragment 中的片段生命周期事件

    我有一个生命周期感知片段和一个LifecycleObserver class public class MyFragment extends Fragment Override public void onCreate Nullable B

随机推荐

  • kafka3.1.0 java 测试demo

    前置条件 首先已经安装的Java环境 并且安装了zookeeper服务注册中心 下载 https kafka apache org 当前最新版本3 1 0 安装 在windows解压后主要关注的是config文件下的server prope
  • 第十一届蓝桥杯C/C++寻找2020

    第十一届蓝桥杯C C 寻找2020 对我来说一开始主要是不会把文本的内容复制去数组里面 后来找了同学帮忙才解决的 直接上代码 结果是16520 include
  • python输入三门课程成绩_python脚本如何输入成绩求平均分?

    python脚本如何输入成绩求平均分 python脚本输入成绩求平均分的方法 脚本要实现功能 1 输入学生学号 2 依次输入学生的三门科目成绩 3 计算该学生的平均成绩 并打印 4 平均成绩保留两位小数点 计算该学生语文成绩占总成绩的百分比
  • 《消息队列高手课》该如何选择消息队列

    作为一个程序员 相信你一定听过 没有银弹 这个说法 这里面的银弹是指能轻松杀死狼人 用白银做的子弹 什么意思呢 我对这句话的理解是说 在软件工程中 不存在像 银弹 这样可以解决一切问题的设计 架构或软件 每一个软件系统 它都是独一无二的 你
  • SpringMVC的文件上传

    SpringMVC的文件上传 SpringMVC的文件上传 1 SpringMVC的请求 文件上传 客户端表单实现 2 SpringMVC的请求 文件上传 文件上传的原理 3 SpringMVC的请求 文件上传 单文件上传的代码实现1 4
  • 春眠不觉晓,redis知多少(2)

    春眠不觉晓 redis知多少 第二篇 4 持久化 4 1 原因 4 2 redis持久化机制 4 2 1 RDB 4 2 2 AOF 5 JAVA客户端 Jedis 5 1 介绍 5 2 使用步骤 5 3 Jedis操作各种redis的数据
  • 【毕设记录】Stata稳健性检验~ Robustness

    一些网上看的 自己用的tips汇总 1 DID 平行趋势检验 自己用的 1 在论文呈现上 可以绘制平行趋势图 也可以做一个Table表示平行趋势检验的结果 2 学习文献的做法 创建政策发生前两年的变量 比如政策是Rights 解释变量是A
  • python情感词典_sentimentpy模块进行中文文本情感分类

    sentimentpy是我根据R语言的一个文本情感分析包sentiment进行开发的 开发的初衷有 R的sentiment已经被弃坑 没人维护 Python比R更擅长文本处理 sentiment包不支持中文 而sentimentpy包有如下
  • nginx源码编译安装出现“make[1]: Leaving directory `/usr/local/nginx’“解决办法

    因为我所有的操作步骤都是按照上面来的 我的解决办法也非常的简单 如果你走到make这一步的时候只出现了一行 make 1 Leaving directory usr local nginx 1 12 1 提示 不用管它 继续走make in
  • 五人合伙最佳股份分配_五人合伙股份分配协议书范本

    股份合作企业与合伙企业是当前改制 改组中倍受关注的企业组织形式 那么合伙股份转让协议书又是怎么一回事呢 以下是在小编为大家整理的合伙股份转让协议书范文 感谢您的阅读 合伙股份转让协议书范文1转让方 甲方 身份证号码 住址 受让方 甲方 身份
  • Unity制作摇杆

    1 导入UGUI与Tools资源包 Unity中就会出现两个插件 2 导入人物模型资源包全部导入完之后 3 新建Plane 把人物模型拖到场景中 4 给人物模型制作动画状态机 4 1找到人物模型动画 并将全部的动画类型设置为Genic类型
  • 串行测试 并行测试_什么是并行测试,为什么要采用它?

    串行测试 并行测试 随着技术的进步 随着组织从手动测试转向Selenium测试自动化 测试解决方案变得比以往更具可扩展性 但是 大多数组织仍在努力的领域之一是可并行运行多个测试的可伸缩性 许多公司仍在使用顺序测试方法来提供质量保证 这会浪费
  • 大学生团体天梯赛(第六届)

    题目地址 天梯赛 include
  • 深度学习8

    Generative Adversarial Network 正如我们前面所说的 GAN里面有两个重要的东西 其中一个就是Generator Generator可以是一个NN 它的输入是一个vector 它的输出是一个更高维的vector
  • JSP-javabean技术

  • ELK 4.5——加入机器学习

    如果你也是 Elaticsearch 的粉丝 或者机器学习的爱好者 你肯定不会错过这个东西 5 月份 Elaticsearch 推出了新版本 5 4 准确地说是 Elastic Stack 全家桶都更新为 5 4 了 在 X pack 中的
  • Angular input延迟防抖debounceTime

    import Component OnInit from angular core import AbstractControl FormBuilder FormGroup Validators from angular forms imp
  • 【代码复现】NER之GlobalPointer解析

    前言 在NER任务中 主要分为三类实体 嵌套实体 非嵌套实体 不连续实体 今天分享方法以end to end的方式解决前两个问题 GlbalPointer 它利用全局归一化的思路来进行命名实体识别 NER 可以无差别地识别嵌套实体和非嵌套实
  • Mysql事务---MVCC详解

    Mysql数据库事务隔离级别 SQL 标准定义了四个隔离级别 READ UNCOMMITTED 读取未提交 事务的修改 即使没有提交 对其他事务也都是可见的 事务能够读取未提交的数据 这种情况称为脏读 READ COMMITTED 读取已提
  • Jetpack学习-1-Lifecycle+Activity源码分析

    解耦是软件开发亘古不变的追求 而Lifecycle正是这一名言的体现 Android开发过程中 有些功能不可避免与页面的生命周期关联 LifeCycle作为Jetpack中具有生命周期感知姓的组件 通过感知activity fragment