NMS Toast

Toast执行流程分析与复用 意图分析的问题 Toast的显示是异步的还是同步。 Toast是否可以在子线程中实例化并调用Toast.show方法。 Toast对象复用的可行性。 源码执行流程分析Toast的本地创建和show()方法实例化Toast对象在实际使用中我们常使用使用如下代码实例化一个Toast对象。Toast.makeText(Context, msg, Toast.LENGTH_SHOW);下面看看makeTex 阅读详情

0x00 NMS Toast

Toast.makeText(Context, "Toast message content.", Toast.LENGTH_SHORT).show();

以下代码分析基于Android 8.1.0

0x01 Toast

Toast类只有500多行,逻辑比较简单,主要有三部分组成: Toast,INotificationManager和TN。Toast类负责构造Toast对象;NotificationManager 负责与 NotificationManagerService交互;TN负责Toast最终的显示。

首先构建一个Toast对象:

public static Toast makeText(@NonNull Context context, @Nullable Looper looper,
        @NonNull CharSequence text, @Duration int duration) {
    // 创建一个Toast对象
    Toast result = new Toast(context, looper);
    // 加载布局,设置Toast要显示的内容
    LayoutInflater inflate = (LayoutInflater)
            context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
    TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
    tv.setText(text);
    // 将加载的View设给Toast
    result.mNextView = v;
    result.mDuration = duration;
    return result;
}

调用Toast.show()方法:

public void show() {
    // mNextView为最终要展示的View,不能为null,Toast创建的时候默认创建一个,也可通过Toast.setView(View view)设置
    if (mNextView == null) {
        throw new RuntimeException("setView must have been called");
    }

    INotificationManager service = getService();
    String pkg = mContext.getOpPackageName();
    TN tn = mTN;
    tn.mNextView = mNextView;

    try {
        // 将TN发给NotificationManagerService
        service.enqueueToast(pkg, tn, mDuration);
    } catch (RemoteException e) {
        // Empty
    }
}

几行代码,获取 INotificationManager 服务。

// =======================================================================================
// All the gunk below is the interaction with the Notification Service, which handles
// the proper ordering of these system-wide.
// =======================================================================================

private static INotificationManager sService;

static private INotificationManager getService() {
    if (sService != null) {
        return sService;
    }
    sService = INotificationManager.Stub.asInterface(ServiceManager.getService("notification"));
    return sService;
}

看到 INotificationManager.Stub.asInterface() 很自然的会去搜 NotificationManagerService,嗯嗯,AOSP
中全局搜索就可以了。至此,Toast的工作做完一半,下来的工作进入 NotificationManagerService。

0x02 NotificationManagerService

frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java

我们来看enqueueToast():

...
final ArrayList<ToastRecord> mToastQueue = new ArrayList<>();
...
private final IBinder mService = new INotificationManager.Stub() {
    // Toasts
    // ============================================================================

    @Override
    public void enqueueToast(String pkg, ITransientNotification callback, int duration)
    {
        if (DBG) {
            Slog.i(TAG, "enqueueToast pkg=" + pkg + " callback=" + callback
                    + " duration=" + duration);
        }

        if (pkg == null || callback == null) {
            Slog.e(TAG, "Not doing toast. pkg=" + pkg + " callback=" + callback);
            return ;
        }
        final boolean isSystemToast = isCallerSystemOrPhone() || ("android".equals(pkg));
        final boolean isPackageSuspended =
                isPackageSuspendedForUser(pkg, Binder.getCallingUid());

        if (ENABLE_BLOCKED_TOASTS && !isSystemToast &&
                (!areNotificationsEnabledForPackage(pkg, Binder.getCallingUid())
                        || isPackageSuspended)) {
            Slog.e(TAG, "Suppressing toast from package " + pkg
                    + (isPackageSuspended
                            ? " due to package suspended by administrator."
                            : " by user request."));
            return;
        }

        synchronized (mToastQueue) {
            int callingPid = Binder.getCallingPid();
            long callingId = Binder.clearCallingIdentity();
            try {
                ToastRecord record;
                int index;
                // All packages aside from the android package can enqueue one toast at a time
                if (!isSystemToast) {
                    index = indexOfToastPackageLocked(pkg);
                } else {
                    index = indexOfToastLocked(pkg, callback);
                }

                // If the package already has a toast, we update its toast
                // in the queue, we don't move it to the end of the queue.
                if (index >= 0) {
                    // Toast已经存在
                    record = mToastQueue.get(index);
                    record.update(duration);
                    record.update(callback);
                } else {
                    // Toast不存在
                    Binder token = new Binder();
                    // 将这个token添加到系统,否则无法正常显示
                    mWindowManagerInternal.addWindowToken(token, TYPE_TOAST, DEFAULT_DISPLAY);
                    record = new ToastRecord(callingPid, pkg, callback, duration, token);
                    // 添加到队列,接下来我们去跟踪这个队列的出口
                    mToastQueue.add(record);
                    index = mToastQueue.size() - 1;
                }
                keepProcessAliveIfNeededLocked(callingPid);
                // If it's at index 0, it's the current toast.  It doesn't matter if it's
                // new or just been updated.  Call back and tell it to show itself.
                // If the callback fails, this will remove it from the list, so don't
                // assume that it's valid after this.
                if (index == 0) {
                    showNextToastLocked();
                }
            } finally {
                Binder.restoreCallingIdentity(callingId);
            }
        }
    }

    @GuardedBy("mToastQueue")
    void showNextToastLocked() {
        // 获取要展示的Toast
        ToastRecord record = mToastQueue.get(0);
        while (record != null) {
            if (DBG) Slog.d(TAG, "Show pkg=" + record.pkg + " callback=" + record.callback);
            try {
                // 显示Toast,这个callback是上面的TN对象,可以看到,这个时候又调回了Toast.TN.show(IBinder windowToken)
                record.callback.show(record.token);
                // 处理Toast显示时间
                scheduleTimeoutLocked(record);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Object died trying to show notification " + record.callback
                        + " in package " + record.pkg);
                // remove it from the list and let the process die
                int index = mToastQueue.indexOf(record);
                if (index >= 0) {
                    mToastQueue.remove(index);
                }
                keepProcessAliveIfNeededLocked(record.pid);
                if (mToastQueue.size() > 0) {
                    record = mToastQueue.get(0);
                } else {
                    record = null;
                }
            }
        }
    }

    @GuardedBy("mToastQueue")
    private void scheduleTimeoutLocked(ToastRecord r)
    {
        // 从这里可以看到,是依赖Handler实现的
        mHandler.removeCallbacksAndMessages(r);
        Message m = Message.obtain(mHandler, MESSAGE_TIMEOUT, r);
        // 这里定义Toast的显示时间,LONG:3.5s, SHORT:2s。注意区分显示时的hideTimeoutMilliseconds
        long delay = r.duration == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY;
        mHandler.sendMessageDelayed(m, delay);
    }
...
};

0x03 Toast.TN

再回到Toast里,这次看里面的TN,从show(IBinder windowToken)开始。

private static class TN extends ITransientNotification.Stub {
    private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();

    private static final int SHOW = 0;
    private static final int HIDE = 1;
    private static final int CANCEL = 2;
    final Handler mHandler;

    int mGravity;
    int mX, mY;
    float mHorizontalMargin;
    float mVerticalMargin;

    View mView;
    View mNextView;
    int mDuration;

    WindowManager mWM;

    String mPackageName;

    // 默认显示时间
    static final long SHORT_DURATION_TIMEOUT = 4000; 
    static final long LONG_DURATION_TIMEOUT = 7000;

    TN(String packageName, @Nullable Looper looper) {
        // XXX This should be changed to use a Dialog, with a Theme.Toast
        // defined that sets up the layout params appropriately.
        final WindowManager.LayoutParams params = mParams;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.format = PixelFormat.TRANSLUCENT;
        params.windowAnimations = com.android.internal.R.style.Animation_Toast;
        params.type = WindowManager.LayoutParams.TYPE_TOAST;
        params.setTitle("Toast");
        params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

        mPackageName = packageName;

        // 子线程显示Toast就会抛这个异常
        if (looper == null) {
            // Use Looper.myLooper() if looper is not specified.
            looper = Looper.myLooper();
            if (looper == null) {
                throw new RuntimeException(
                        "Can't toast on a thread that has not called Looper.prepare()");
            }
        }
        mHandler = new Handler(looper, null) {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case SHOW: {
                        // (2) 拿到token,展示
                        IBinder token = (IBinder) msg.obj;
                        handleShow(token);
                        break;
                    }
                    case HIDE: {
                        handleHide();
                        // Don't do this in handleHide() because it is also invoked by
                        // handleShow()
                        mNextView = null;
                        break;
                    }
                    case CANCEL: {
                        handleHide();
                        // Don't do this in handleHide() because it is also invoked by
                        // handleShow()
                        mNextView = null;
                        try {
                            getService().cancelToast(mPackageName, TN.this);
                        } catch (RemoteException e) {
                        }
                        break;
                    }
                }
            }
        };
    }

    /**
     * (1) schedule handleShow into the right thread
     */
    @Override
    public void show(IBinder windowToken) {
        if (localLOGV) Log.v(TAG, "SHOW: " + this);
        // 发送显示Toast的Message
        mHandler.obtainMessage(SHOW, windowToken).sendToTarget();
    }

    /**
     * schedule handleHide into the right thread
     */
    @Override
    public void hide() {
        if (localLOGV) Log.v(TAG, "HIDE: " + this);
        mHandler.obtainMessage(HIDE).sendToTarget();
    }
    /**
     * hide 和 cancel逻辑相同
     */
    public void cancel() {
        if (localLOGV) Log.v(TAG, "CANCEL: " + this);
        mHandler.obtainMessage(CANCEL).sendToTarget();
    }

    /**
     * (3)真正展示Toast的地方,最终还是WindowManager.addView()
     * @param windowToken 展示Toast的token
     */
    public void handleShow(IBinder windowToken) {
        if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
                + " mNextView=" + mNextView);
        // If a cancel/hide is pending - no need to show - at this point
        // the window token is already invalid and no need to do any work.
        if (mHandler.hasMessages(CANCEL) || mHandler.hasMessages(HIDE)) {
            return;
        }
        // Toast没有显示过或者当前不再显示状态
        if (mView != mNextView) {
            // remove the old view if necessary
            // 移除之前的View
            handleHide();
            mView = mNextView;
            Context context = mView.getContext().getApplicationContext();
            String packageName = mView.getContext().getOpPackageName();
            if (context == null) {
                context = mView.getContext();
            }
            // 世界的本源
            mWM = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
            // We can resolve the Gravity here by using the Locale for getting
            // the layout direction
            // 以下配置Toast的显示参数
            final Configuration config = mView.getContext().getResources().getConfiguration();
            final int gravity = Gravity.getAbsoluteGravity(mGravity, config.getLayoutDirection());
            mParams.gravity = gravity;
            if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
                mParams.horizontalWeight = 1.0f;
            }
            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {
                mParams.verticalWeight = 1.0f;
            }
            mParams.x = mX;
            mParams.y = mY;
            mParams.verticalMargin = mVerticalMargin;
            mParams.horizontalMargin = mHorizontalMargin;
            mParams.packageName = packageName;
            // 显示超时时间
            mParams.hideTimeoutMilliseconds = mDuration ==
                Toast.LENGTH_LONG ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT;
            // 要显示,token是必须的
            mParams.token = windowToken;
            // 这种方法可以判断当前View是否正在显示,如果显示就remove掉
            if (mView.getParent() != null) {
                if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
                mWM.removeView(mView);
            }
            if (localLOGV) Log.v(TAG, "ADD! " + mView + " in " + this);
            // Since the notification manager service cancels the token right
            // after it notifies us to cancel the toast there is an inherent
            // race and we may attempt to add a window after the token has been
            // invalidated. Let us hedge against that.
            try {
                // 好了,真正的开始显示了
                mWM.addView(mView, mParams);
                trySendAccessibilityEvent();
            } catch (WindowManager.BadTokenException e) {
                /* ignore */
            }
        }
    }

    private void trySendAccessibilityEvent() {
        AccessibilityManager accessibilityManager =
                AccessibilityManager.getInstance(mView.getContext());
        if (!accessibilityManager.isEnabled()) {
            return;
        }
        // treat toasts as notifications since they are used to
        // announce a transient piece of information to the user
        AccessibilityEvent event = AccessibilityEvent.obtain(
                AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
        event.setClassName(getClass().getName());
        event.setPackageName(mView.getContext().getPackageName());
        mView.dispatchPopulateAccessibilityEvent(event);
        accessibilityManager.sendAccessibilityEvent(event);
    }
    /**
     * hide逻辑比较简单,直接remove掉就可以了
     */
    public void handleHide() {
        if (localLOGV) Log.v(TAG, "HANDLE HIDE: " + this + " mView=" + mView);
        if (mView != null) {
            // note: checking parent() just to make sure the view has
            // been added...  i have seen cases where we get here when
            // the view isn't yet added, so let's try not to crash.
            if (mView.getParent() != null) {
                if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
                mWM.removeViewImmediate(mView);
            }
            // 隐藏后mView被置空
            mView = null;
        }
    }
}

至此,分析完毕。

0x03 疑问

  1. Toast为什么设计成一个远程调用?
  2. Toast和Notification什么关系?

这两个问题需要站在系统的角度考虑。简单谈谈我的理解。Toast和Notification都是系统提供的展示通知的基础组件,所有的APP都可以调用。所有的APP都可以调用,那系统就需要有一定的控制权,不然可能会被滥用。有些ROM显示Toast是需要系统授权的从侧面印证了这点。

0x04 答疑

  • Toast能改显示时间吗?

不可以,Toast的显示时间由系统决定,使用者只能从Toast.LENGTH_SHORT(4s)/Toast.LENGTH_LONG(7s)两种方式中选择一种。

  • 能不能改显示动画?

不可以,Toast.getWindowParams()为hide方法,不可以直接调用。

  • 创建Toast时对传入的Context有要求吗?

这个context有两个作用,inflate出Toast要展示的内容和获取包名等信息。这两个操作对Context都无特殊要求,Application,Activity,Service,BroadcastReceiver的Context都可以。

  • 如果我有两个屏幕,可以在第二个屏幕上显示Toast吗?

显示Toast的Token在创建时使用的DEFAULT_DISPLAY,因此不可以显示在第二块屏幕上。

0xFF 参考

  1. https://blog.youkuaiyun.com/lmj623565791/article/details/40481055
Android25上Toast的BadTokenException问题 一、问题: 在公司的crash平台上发现了这个crash,机型分布很杂乱,但是都分布在Android25上,量也挺大的,1w的DAU有40个crash,算TopCrash了。其实之前这个crash就一直存在了,但是这次突然crash量大增,没办法就分给我解决啦。先看CrashLog: android.view.WindowManager$BadTokenException: Unable to... 阅读详情

相关推荐

全面掌握Android Toast应用技巧

本文还有配套的精品资源,点击获取 简介:在Android开发中,Toast是一种非常实用的提示机制,用于显示短暂的信息,如操作成功或失败提示。本文详细介绍了Toast的基本使用方法,包括创建Toast对象、设置显示位置、显示Toast、自定义View、取消Toast以及一些注意事项。同时,本文也探讨了Toast与Android UI元素的结合使用,帮助开发者提升应用用户体验...

weixin_42599908的博客 2415

android源码学习-Toast实现原理讲解

Toast的全流程讲解,包含原生Toast和自定义Toast两种方式。 Toast相关的常问的知识点以及使用Toast过程中频繁遇到的问题和解决方案。

分享+记录 5428

SAP中错记虚拟利润中心的调整,冲销处理实例

我非CO专业顾问。工作中遇到的问题,也会找资料,分析,测试。有时这个过程会拿到结果,解决问题。遂将过程记录下来备查。读者请谨慎参考!EC-PCA: 利润中心记账流程_9ke0-优快云博客。

专注SAP应用技术文章写作,致力于拉近用户与系统间的距离; 1799

Android 11适配指南之Toast解析

起源 在targetSdkVersion为30的情况下,在Android 11的小米10的手机上运行,调用ToastUtil的时候闪退报错: null cannot be cast to non-null type android.widget.LinearLayout 为什么说的这么详细呢,因为这些条件都是必须的: targetSdkVersion 30 Android 11 小米10 同样的targetSdkVersion,在Android 11的华为P30 Pro上运行确实正常的,为什么呢,根据

yechaoa 6387

【计算机视觉40例】案例08:石头剪刀布手势识别

计算机视觉40例——从入门到深度学习(OpenCV-Python)》在介绍Python基础、OpenCV基础、计算机视觉理论基础、深度学习理论的基础上,介绍了计算机视觉领域内具有代表性的40个典型案例。这些案例中,既有传统的案例(数字识别、答题卡识别、物体计数、缺陷检测、手势识别、隐身术、以图搜图、车牌识别、图像加密、指纹识别等),也有深度学习案例(图像分类、风格迁移、姿势识别、实例分割等),还有人脸识别方面的案例(表情识别、驾驶员疲劳监测、识别性别与年龄等)。......

计算机视觉之光 2157

机械臂视觉抓取避坑指南:如何正确计算手眼标定矩阵(附Numpy代码)

本文详细解析了机械臂视觉抓取中手眼标定矩阵的计算方法,特别针对'眼在手上'配置下的常见错误提供了解决方案。通过Numpy代码示例和坐标转换原理,帮助开发者避免矩阵计算错误和坐标转换偏差,提升工业自动化系统的精度和效率。

weixin_29081703的博客 244

Toaster框架深度解析:打造灵活高效的Android Toast解决方案

在Android开发中,Toast作为轻量级的消息提示机制被广泛应用。然而,系统原生Toast存在诸多限制和问题,Toaster框架应运而生,为开发者提供了更强大、更灵活的Toast解决方案。本文将深入解析Toaster框架的核心功能和使用技巧,帮助开发者更好地理解和应用这一工具。 ## 动画效果定制 Toaster框架允许开发者完全自定义Toast的显示动画效果,这是系统Toast无法实现的...

gitblog_00028的博客 625

Nifi SNI 问题解决方案

Nifi 在配置 SSL 时,如果没有正确设置主机名(SNI),就会导致。为了解决这个问题,我们需要重新配置 Nifi 的 SSL 证书,并确保所有相关配置项(如服务器地址、证书路径和密码等)正确无误。以下是一个详细的解决步骤,以帮助你正确配置 Nifi 并解决 SNI 错误。文件中的配置项(如服务器地址、端口和证书路径),以及正确设置用户凭证。通过这些配置,你可以确保 Nifi 在支持 HTTPS 的同时,正确处理 SSL/TLS 的 SNI 问题。文件,配置服务器地址、端口以及证书路径和密码。

m0_58786911的博客 2299

Android窗口机制:八、Toast机制-(封装可以在任何线程使用的toast)。(源码版本SDK31)

Toast机制源码分析,源码版本SDK31. 封装可以在任何线程调用的toast

Pumpkin's Blog 4919

pytorchDataLoader中调整数据长度不一致问题(lstm等)

数据长度不一致 用pytorch做rnn的时候,如果输入数据不一样长,可以用两种方式解决。 一种是自定义collate方法, #自定义collate_fn dataloader.DataLoader(dataset,4,True,collate_fn=my_collate) 然后里面写数据和标签载入方式即可 def my_collate(batch): data = [item[0] for item in batch] target = [item[1] for item in batc

weixin_48174100的博客 7771

【STM32项目】基于STM32设计的震动马达超声波电机高频震动——高级定时器PWM互补输出带死区控制__资料编号3

实现高级定时器互补输出带死区控制,实现震动/超声波电机/马达,高频震动。使用 STM32F103 芯片输出两路互补 PWM,并带有死区和刹车控制功能。定时器 1 通道 1 及其互补通道输出PWM,且带死区控。当定时器 1 的刹车输入引脚被拉高时,产生刹车时间,即定时器 8 停止输出 PWM。当刹车输入引脚被拉高时,通道 1 和通道 2 将从有波形输入状态转换成无效电平状态。

嵌入式阿齐Archie 6742

Toast源码解析

android 源码分析 Toast

hyc1988107的博客 944

运维系列【仅供参考】:RustDesk部署疑难解答

RustDesk部署疑难解答

weixin_54626591的博客 283

同学,你的系统Toast可能需要修复一下

光有这些思路和搞懂单个知识的应用是还远远不够的,在Android开源框架设计思想中的知识点还是比较多的,想要搞懂还得学会整理和规划:我们常见的**Android热修复框架、插件化框架、组件化框架、图片加载框架、网络访问框架、RxJava响应式编程框架、IOC依赖注入框架、最近架构组件Jetpack等等Android第三方开源框架,**这些都是属于Android开源框架设计思想的。如下图所示:这位阿里P8大佬针对以上知识点,熬夜整理出了一本长达1042页的完整版如何解读开源框架设计思想。

m0_60607971的博客 760

基于STM32H5的循环GPDMA链表使用

STM32H503的GPDMA链表模式可实现灵活的数据传输。相比传统DMA直接编程方式,链表模式通过配置多个节点实现分散数据传输,支持循环链表功能。示例展示了如何使用GPDMA链表实现UART1循环发送数据:配置两个DMA节点分别指向不同发送缓冲区,构建循环链表并绑定到DMA通道。关键点包括:清空链表结构体、正确设置循环模式、检查节点配置。此方法提高了DMA使用的灵活性,适用于需要交替传输多段数据的场景。

kevin1499的博客 453

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Android Toast机制实现原理

Toast的实现原理 通过本文,你将懂得: 1. 为什么调用Toast的子线程需要Looper.prepare() 2. Toast的Window是在哪里创建的 Toast中的IPC通信 在Toast的实现中主要有两类IPC通信: 1. 从Toast通过IPC访问NotificationManagerService(以下简称NMS) 2. 从NMS通过IPC访问Toast 其中...

mingC0758的博客 1567

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

一文读懂Toast显示流程

Toast的显示流程分析;两种Toast类型的调度机制,以及App进程,system_server和SystemUI的跨进程调用过程

weixin_43837293的博客 1948

贝叶斯统计 [韦来生编]

贝叶斯(Bayes)统计是近几十年来迅速发展起来的数理统计的一个重要分支。贝叶斯方法与经典统计方法的主要不同之处是进行统计推断时除了利用样本信息外,还要利用参数的先验信息,因此可以提高统计推断或统计决策的效果。它在经济、金融、生物、医学、自然科学和社会科学等许多领域具有广泛的应用。贝叶斯方法的研究已渗透到了统计学的几乎所有领域。作者在给中国科学技术大学概率论与数理统计专业本科生开设的“数理统计”课程中有一章专门讲授“贝叶斯方法和统计决策理论”,近十年来也给中国科学技术大学概率统计专业研究生开设过几次“贝叶斯分析”课。本书是在对过去讲稿的内容作了适当的增减和调整的基础上完成的。  本书共分六章。第1章是绪论,介绍了贝叶斯统计的若干基本概念,同时对必要的数理统计的基础知识有重点地作了回顾。第二章介绍了确定先验分布的若干可供选择的方法。第三章介绍了几类常见统计模型参数的后验分布的主要结果和计算方法。第四章和第五章分别介绍了“贝叶斯统计推断”和“贝叶斯统计决策”的内容。第六章介绍了贝叶斯统计计算的若干方法,包括蒙特卡洛方法和马尔可夫链蒙特卡洛(MCMC)方法以及相关统计软件的简介。本书的每一章附右大量的例题和习题,书末附有常用的几个表格和部分习题解答供读者查用。  大约可在54学时内讲授本书的第1章至第六章的主要内容,教师可根据学时需要选讲本书第1章至第六章的部分内容。书中标“*”号的章节可略去不讲,留给读者作为阅读材料。第六章例题中的R代码和部分例题的数据文件等可从作者个人主页下载。  作者在编写本书的过程中参考了J.O.Berger教授的《统计决策论及贝叶斯分析》和茆诗松教授编写的《贝叶斯统计》等书中的一些内容,以及《贝叶斯分析》一书中由张伟平博士编写的有关贝叶斯统计计算的一些内容。在此表示衷心感谢。  本书编写准备过程中,中国科学技术大学统计与金融系的几个研究生帮助完成了本书部分中文的录入和排版,作者对他们的辛勤工作表示真诚的感谢。高等教育出版社为本书的出版给予了大力支持。在此一并致谢。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

KMS_VL_ALL_AIO 激活 Windows 和 Office:5 分钟、免服务器、零残留的完整操作路径

KMS_VL_ALL_AIO 激活脚本是一个不到 300KB 的开源免费批处理文件,替个人用户和 IT 管理员完成 Windows 批量激活与 Office KMS 激活:检测环境、装密钥、免服务器激活、KMS 自动续期,一次配完,重启后状态保持。新手照着下面的顺序做,5 分钟走完全部流程。 ## 开工前 30 秒自检 四条都过,后面的步骤基本不会卡。任何一条不过,先把它修好再动手。 | 检

gitblog_00409的博客 121

Android 15 AOSP Notification分析

Android 15 AOSP 通知系统架构摘要: Android通知系统采用多层架构设计,包含应用层、Framework层和SystemUI层。核心组件NotificationManagerService(NMS)负责通知生命周期管理,通过Binder IPC与应用层NotificationManager交互。系统包含NotificationRecord、RankingHelper、GroupHelper等关键类,实现通知排序、分组等功能。数据流从应用发起通知请求开始,经过权限检查、信号提取、排序处理后,

wxz的博客 3306

toast弹窗_同学,你的系统Toast可能需要修复一下

先看看使用系统Toast存在的问题:1.当通知权限被关闭时在华为等手机上Toast不显示;2.Toast的队列机制在不同手机上可能会不相同;3.Toast的BadTokenException问题;当发现系统Toast存在问题时,不少同学都会采用自定义的TYPE_TOAST弹窗来实现相同效果。虽然大部分情况下效果都是OK的,但其实TYPE_TOAST弹窗依然存在兼容问题:4.Android8.0之后...

weixin_39657575的博客 1235

Toast与Snackbar的那点事

我们的核心目标只是希望在用户关闭通知消息开关的情况下,能继续看到通知,所以我们使用了WindowManager添加自定义window的方式来替换Toast,但是在替换的过程中遇到了一些Toast的Crash异常,为了解决这些Crash,我们提出了使用自定义ToastHandler的方式来catch住异常,确保app正常运行。在方案推广上,为了能用更少的人力,更高的效率完成替换,我们使用了AspectJ的方案。

2501_90251165的博客 1260

Toast的Window创建过程

Toast和Dialog不同,它的工作过程就稍显复杂。首先Toast也是基于Window来实现的,但是由于Toast具有定时取消这一功能,所以系统采用了Handler。在Toast的内部有两类IPC过程,第一类是Toast访问NotificationManagerService,第二类是Notification-ManagerService回调Toast里的TN接口。 Toast属于系统Wind...

Lud的博客 699

Toast显示过程

2018-08-03 11:35:14 文章目录 抄书抄的有点烦,自己也学着分析一下源码,挑了个在我看来比较简单的Toast显示过程来玩一玩。 Toast.makeText(context, text, duration).show(); 先了解一下makeText过程,该过程最终都会调用下面的方法: /** * Make a standard toast to display using the specified looper. * If looper is null, Loope

Huang兄 797
上一篇: RockChip主板系统签名说明
下一篇: Apk静默安装之调用系统隐藏API
ttdevs
博客等级 码龄15年 388粉丝 91原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值