Android:关于Window少为人知的一面

Android全面解析Window机制 先假设如果没有window,会发生什么:我们看到的界面ui是view,如我们的应用布局,更简单是一个button。假如屏幕上现在有一个Button,如图1,现在往屏幕中间添加一个TextView,那么最终的结果是图2,还是图3:在上图的图2中,如果我要实现点击textView执行他的监听事件逻辑,点击不是textView的区域让textView消失,需要怎么实现呢? 阅读详情

转自:https://www.jianshu.com/p/f9c3c9a19772?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

前言

大部分情况下,我们和Window打交道的情况比较少,一般都是与Activity和View“交流”。最近做了不少与Window相关的工作,梳理了下Window相关的知识,在此,与大家分享下。关于系统源码相关的知识如何介绍,其实是比较费神,如果只是贴出源码,做出解释,其实不好理解和记忆,并且网上关于源码分析的文章太多太多。因此,我会结合例子来演示,并把常见问题贴出来并加以分析。我相信,以后面试的时候,你可能会碰到此类问题。

知识点

Window是什么
首先看下官方的定义:

Abstract base class for a top-level window look and behavior policy. An instance of this class should be used as the top-level view added to the window manager. It provides standard UI policies such as a background, title area, default key processing, etc.
The only existing implementation of this abstract class is PhoneWindow, which you should instantiate when needing a Window.

大概翻译如下:
Window类是一个抽象类,它定义了顶级窗体样式和行为。一个Window实例应作为顶级View添加到WindowManager中。它提供标准的UI规则,例如背景、标题、默认关键过程等。

Window有且仅有一个实现类PhoneWindow,如果我们需要Window实例化PhoneWindow即可。

看到这,其实还是云里雾里,并没有一个切身的体会,所以还是要继续分析。

Window的类型

在WindowManager中定义了许多Window类型,总共分为以下三类。
1、Application Window。Value from 1 to 99 .
比如:activity、dialog…
2、Sub Window。Value from 1000 to 1999.
比如:ContextMenu、PopupWindow…
3、System Window。Value from 2000 to 2999.
比如:Toast、SystemAlert、 InputMethod...
关于此处更详细的讲解请参考浅析Android的窗口,本文不做重复介绍。此文解释的非常全面。

Window token

token这个词我们在开发的时候可能碰到过,比如某些Dialog的异常信息就经常会报bad Token错误。那么Window token起了什么作用。大部分Window Token都是IBinder或者IInterface对象,之所以用IBinder或者IInterface,因为它们能用于跨进程间通信,能够用于Window的身份验证,是Window与WMS(WindowManagerService)交流的凭证。在浅析Android的窗口"token的含义"中更详细的介绍,可以作为参考。
WindowManager.LayoutParams类中有个token字段。

 /**
         * Identifier for this window.  This will usually be filled in for
         * you.
         */
        public IBinder token = null;

父窗口和其子窗口的token对象是同一个,一般都是父窗口赋给子窗口。
在Window中有个方法adjustLayoutParamsForSubWindow就是用于把父窗口的token复制给子窗口。
如果Window没有父窗口,那么会由WMS为其创建token。

Window的显示过程

window显示过程

 

Window显示的过程还是挺复杂的,不过其中我们只需关注几个核心类的即可,比如ViewRootImpl、WindowManagerService。
另外这其中有个Session类,该类的作用是用于单独标识每个进程,与token的作用类似,只不过token是代表标识Window。

创建一个Window试试

在Activity中,运行下述方法。

    private void generateSystemAlert() {
        //Activity Context
        WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        //Application Context
        //WindowManager wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
        final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
        params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        params.width = WindowManager.LayoutParams.MATCH_PARENT;
        params.height = 500;
        params.gravity = Gravity.CENTER;
        final View view = LayoutInflater.from(this).inflate(R.layout.window_system_alert, null);
        wm.addView(view, params);
    }

创建Window

添加Window的过程和往ViewGroup中添加View的过程相当类似。WindowManager管理Window的添加、移除等操作。

WindowManager是一个接口,应用程序可以通过WindowManager来与系统Window服务交流。我们可以通过
Context.getSystemService(Context.WINDOW_SERVICE)
来获取WindowManager实例。
在上述代码中,我采取了两种不同的方式获取WindowManager对象。一种是直接调用Activity中的getSystemService方法,另外一种是通过调用Application Context的getSystemService方法。

WindowManager不同获取方式的效果

通过实践可以得知:
用Application Context获取的WindowManager实例来创建Window并不随Activity的消失而消失,只有当进程被杀的时候才消失。
用Activity Context获取的WindowManager实例来创建Window随Activity的消失而消失。
另外,上面的动态图演示的时候,当按下返回键的时候,应用程序打印如下错误。

E/WindowManager: android.view.WindowLeaked: 
Activity com.kisson.windowtest.MainActivity has leaked window 
android.support.v7.widget.AppCompatTextView{1b90179 V.ED.... ......I. 0,0-1080,200 #7f0c0061 app:id/tv} that was originally added here
                         at android.view.ViewRootImpl.<init>(ViewRootImpl.java:363)
                         at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:271)
                         at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
                         at com.kisson.windowtest.MainActivity.generateSystemAlert(MainActivity.java:93)
                         at com.kisson.windowtest.MainActivity.access$100(MainActivity.java:15)
                         at com.kisson.windowtest.MainActivity$2.onClick(MainActivity.java:31)
                         at android.view.View.performClick(View.java:4780)
                         at android.view.View$PerformClick.run(View.java:19866)

这个报错我们应该不陌生--“窗体泄露”。特别是使用Dialog的时候,如果Dialog未dismiss,某种情况下就会导致窗体泄露,所以Android提供了DialogFragment来解决此类问题。

通过以上演示,我们可以得出以下问题:
1、为什么获取WindowManager的Context类型不同,导致Window的生命周期不同。
2、什么情况下发生窗体泄露。

看源码分析问题

1.Application Context的getSystemService方法
Application Context调用的getSystemService方法是Context抽象类中的一个抽象方法,该方法的实现是在ContextImpl类中。

    @Override
    public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }

在SystemServiceRegistry类中,找到注册WINDOW_SERVICE方法如下。

 registerService(Context.WINDOW_SERVICE, WindowManager.class,
                new CachedServiceFetcher<WindowManager>() {
            @Override
            public WindowManager createService(ContextImpl ctx) {
                return new WindowManagerImpl(ctx.getDisplay());
            }});

从此,我们可以看到创建WindowManager对象,最后是调用WindowManagerImpl(Display display)构造方法创建。暂且分析到这,读者有兴趣的话可以追踪源码来分析。
2.Activity的getSystemService方法

@Override
public Object getSystemService(@ServiceName @NonNull String name) {
        if (getBaseContext() == null) {
            throw new IllegalStateException(
                    "System services not available to Activities before onCreate()");
        }

        if (WINDOW_SERVICE.equals(name)) {
            return mWindowManager;
        } else if (SEARCH_SERVICE.equals(name)) {
            ensureSearchManager();
            return mSearchManager;
        }
        return super.getSystemService(name);
    }

从代码可知,Activity重写了getSystemService,当传入的参数ServiceName等于WINDOW_SERVICE,直接返回mWindowManager对象。接着,分析mWindowManager是如何创建。
在Activity的attach方法,创建了mWindowManager实例。

final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
        //......
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;
    }

mWindowManager是在mWindow(mWindow是Window的实例)的setWindowManager方法中创建。接着来看下setWindowManager方法做了什么。

    public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
        mAppToken = appToken;
        mAppName = appName;
        mHardwareAccelerated = hardwareAccelerated
                || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
        if (wm == null) {
            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        }
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    }

在setWindowManager方法中有个参数也是WindowManager对象(该对象就是ContextImpl中getSystemService获取到的),然后调用该对象的createLocalWindowManager方法创建Activity的mWindowManager实例。

    public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
        return new WindowManagerImpl(mDisplay, parentWindow);
    }

到此就明朗,通过调用WindowManagerImpl(Display,Window)的构造方法创建mWindowManager对象。

所以我们可得出Application Context和Activity Context创建的WindowManager对象是通过WindowManagerImpl不同的构造方法来创建的。

    public WindowManagerImpl(Display display) {
        this(display, null);
    }

    private WindowManagerImpl(Display display, Window parentWindow) {
        mDisplay = display;
        mParentWindow = parentWindow;
    }

Application Context创建的WindowManagerImpl对象是没有父窗口(parentWindow)。
Activity Context创建的WindowManagerImpl对象会将Activity的mWindow作为父窗口。
通过分析和前面的演示,可以得出结论。
1.如果某个Window有parentWindow,当parentWindow remove之后,子窗口也会被remove。
2.若有子Window未remove,则会出现窗体泄露错误信息。

有结论了,接下来就验证下。
对Android源码搜索报错关键句“that was originally added here”,发现在WinowManagerGlobal的closeAll方法出现该语句。其实从该方法的名字就可以猜出来,关闭所有窗口。

    public void closeAll(IBinder token, String who, String what) {
        synchronized (mLock) {
            int count = mViews.size();
            //Log.i("foo", "Closing all windows of " + token);
            for (int i = 0; i < count; i++) {
                //Log.i("foo", "@ " + i + " token " + mParams[i].token
                //        + " view " + mRoots[i].getView());
                if (token == null || mParams.get(i).token == token) {
                    ViewRootImpl root = mRoots.get(i);

                    //Log.i("foo", "Force closing " + root);
                    if (who != null) {
                        WindowLeaked leak = new WindowLeaked(
                                what + " " + who + " has leaked window "
                                + root.getView() + " that was originally added here");
                        leak.setStackTrace(root.getLocation().getStackTrace());
                        Log.e(TAG, "", leak);
                    }

                    removeViewLocked(i, false);
                }
            }
        }
    }

接着,看下closeAll在哪调用。继续搜索,发现在ActivityThread的handleDestroyActivity方法中调用了closeAll方法。

private void handleDestroyActivity(IBinder token, boolean finishing,
            int configChanges, boolean getNonConfigInstance) {
        ActivityClientRecord r = performDestroyActivity(token, finishing,
                configChanges, getNonConfigInstance);
        //......
            if (r.mPendingRemoveWindow == null) {
                //读者可以仔细体会此段英文
                // If we are delaying the removal of the activity window, then
                // we can't clean up all windows here.  Note that we can't do
                // so later either, which means any windows that aren't closed
                // by the app will leak.  Well we try to warning them a lot
                // about leaking windows, because that is a bug, so if they are
                // using this recreate facility then they get to live with leaks.
                WindowManagerGlobal.getInstance().closeAll(token,
                        r.activity.getClass().getName(), "Activity");
            }
    //......
    }

到此,可以知道,在Activity destroy时,会去检查是否有窗体泄露。

这里我们要注意,窗体泄露只会在堆栈中打印错误信息,不会导致应用程序崩溃。

从Activity到Window

Activity使我们开发过程中最经常打交道的组件,因此从Activity和Window的关系,可以更好的帮助我们理解Window是啥玩意。
创建页面布局,我们都是通过调用Activity的setContentView方法

    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

从这里,我们可以知道,最终是调用Window的setContentView方法,该方法的实现是在PhoneWindow中。

@Override
    public void setContentView(int layoutResID) {
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }

从该代码中,大概做了如下操作:

  1. installDecor.
    1).generateDecor
    2).generateLayout
  2. inflate your layout.

DecorView是一个自定义FrameLayout,它是作为Activity中Window的顶级View,比如状态栏,标题栏等。因为每个非全屏Activity都显示状态栏,所以系统把某些共性的View都抽象出来,避免我们做重复工作。如果各位想要更深入了解DecorView,可以结合网上资料进行理解。generateDecor的过程就是创建DecorView的过程。

每个Activity都是有自己资源ID形式的布局。在填充资源layout时候,会根据不同的feature来选择不同的布局。
大概有如下几种。

R.layout.screen_title_icons
R.layout.screen_progress
R.layout.screen_custom_title
R.layout.screen_action_bar
R.layout.screen_simple_overlay_action_mode;
R.layout.screen_simple

接着我们来来看R.layout.screen_simple布局是什么样子。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical">
    <ViewStub android:id="@+id/action_mode_bar_stub"
              android:inflatedId="@+id/action_mode_bar"
              android:layout="@layout/action_mode_bar"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:theme="?attr/actionBarTheme" />
    <FrameLayout
         android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:foregroundInsidePadding="false"
         android:foregroundGravity="fill_horizontal|top"
         android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>

在AndroidUI优化实践有介绍,ViewStub用于懒加载actionBar,而id为@android:id/content的FrameLayout,此FrameLayout就是contentView。我们在Activity中调用setContentView方法,设置布局,最终就是添加到该FrameLayout中。

Activity中View层级

从上图中,我们很清楚的看到整个View的层次。DecorView最为Activity Window中的顶级View。

分析到这里,整个Activity需要显示的View创建好了,那么如何显示?
在Activity中,我并未找到显示DecorView的方法。根据阅读源码经验,应该会在ActivityThread中。
在ActivityThread的handleResumeActivity中

if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }

我们可以看到DecorView通过wm添加到系统中。

创建Window的实质

从以上的分析,我们可以得出创建Window的过程其实就是添加View的过程。比如Activity中decorView是作为顶级View添加到系统中去显示,顶级View的LayoutParams必须是WindowManager.LayoutParams类型,否则会报错。那么为什么会有Window的存在,我们直接用添加View形式,创建Activity所需显示的界面不久就了。
这里就又回到最初Window的定义,Window它定义了顶级窗体样式和行为。因为每个Activity都会标题栏,状态栏等,在Window中它提供了DecorView的创建,省去我们不少麻烦,通过Window提供API,我们可以很方面改变标题栏,状态栏的样式。同时Window也提供某些共性操作的行为,比如返回键操作、触摸事件传递,menu显示与因此等。Window最核心的内容还是它提供的顶级View--DecorView及其相关操作。

最后

Window在我们开发过程中起着至关重要的地位。因此,深入了解Window对我们解决一系列UI问题大有裨益。你深入了解Window后就会知道:
1.为什么Dialog的创建必须要用Activity Context。
2.为什么PopupWindow的生命周期与Activity绑定。
3.为什么我创建的Window不能显示、不能点击等等。



作者:Kisson
链接:https://www.jianshu.com/p/f9c3c9a19772
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

Android 11----Context.getWindowManager().getDefaultDisplay().getSize()详解 (上) 基本上做过Android的同学都知道,context无处不在,Activity,Service,Application都是Context,view也有context,我们可以通过context 阅读详情

相关推荐

Android 8应用获取上层系统全局Window的区域

Android8应用获取上层系统全局Window的区域简介原理具体实现 简介 项目中遇到了一个需求,就是需要知道一个Activity或者通过WindowManager.addView添加的上层所有视图的区域,比如其他Activity,或者其他windowManager通过addView接口添加的window,以供业务实现使用。同时还需要在window更新位置,消失,显示时候,通知客户端。 经过对源码的了解,确定了大体方案。 原理 我们先了解下系统添加window的大体流程。 ![在这里插入图片描述](ht

u014779793的博客 3335

Dialog使用时has leaked window...that was originally added here错误

错误提示android.view.WindowLeaked: Activity … has leaked window … that was originally added here分析:经常在应用中需要处理一些耗时的工作,诸如读取大文件、访问网络资源等。为了避免因程序假死而带来的糟糕用户体验,通常我们可以通过线程+Handler或者Android提供的AsyncTask来解决该问题,并一般以Di

Maxi的专栏 1万+

Android中Window添加View的底层原理

一,WIndow和windowManager Window是一个抽象类,它的具体实现是PhoneWindow,创建一个window很简单,只需要创建一个windowManager即可,window具体实现在windowManagerService中,windowManager和windowManagerService的交互是一个IPC的过程。 下面是用windowManager的例子

u014486880的博客 5738

that was originally added here

错误:Activity com.jixtech.acplay.activitys.HomeActivity has leaked window DecorView@ee21a5f[HomeActivity] that was originally added here 导致错误的是

西红柿超级无敌好吃的博客 1855

Android之Window与WindowManager

  【参考资料】 Android Activity应用窗口的创建过程分析

大逗的博客 816

Android解析Window机制

一、window介绍 什么是window 什么是view树?例如你在布局中给Activity设置了一个布局xml,那么最顶层的布局如LinearLayout就是view树的根,他包含的所有view就都是该view树的节点,所以这个view树就对应一个window。 Activity、popupWindow、Toast、dialog、menu都有自己的view树,分别对应不同的window view树是window的存在形式,window是view树的载体 window是view树的管理者,同时也是

shipingxue的专栏 1842

Android全面解析之Window机制

带你认识最本质Android的window机制

一只修仙的猿 1万+

Android解析WindowManager(二)Window的属性

在上一篇文章我们学习了WindowManager体系,了解了Window和WindowManager之间的关系,这一篇我们接着来学习Window的属性。

Android进阶三部曲 - 刘望舒 7487

Android Window

Window,即窗口,在 Android 中,它是一个抽象的东西,我们在日常开发中,直接接触到的东西是 View,而 View 是附着在 Window 之上的。所以我们也可以说 Window 是 View 的直接管理者。

liuning1985622的博客 1146

Android应用程序窗口(Activity)的窗口对象(Window)

每一个Activity组件都有一个关联的ContextImpl对象,同时,它还关联有一个Window对象,用来描述一个具体的应用程序窗口。每一个Activity组件都有一个关联的ContextImpl对象,同时,它还关联有一个Window对象,用来描述一个具体的应用程序窗口。由此又可知,Activity只不过是一个高度抽象的UI组件,它的具体UI实现其实是由其它的一系列对象来实现的。在本文中,我们就将详细分析Android应用程序窗口对象的创建过程。为了方便接下来描述类型为PhoneWindow的应用程序窗口的创建过程,我们将这两个图拿过来,如以下的图1和图2所示:图1Activity和Win

ArcGis布局视图中Excel表格无边框插入与图例符号边框定制技巧

本文详细解析了在ArcGis布局视图中实现Excel表格无边框插入与图例符号边框定制的专业技巧。通过源头净化Excel表格、精准粘贴以及分解图例并单独设置边框属性,有效解决了地图报告中常见的视觉粗糙问题,帮助用户提升专题图与报告的精致度与专业感。

weixin_29292535的博客 305

Android:Window相关理解

有关Window的相关理解

qjyws的博客 2524

从零到一:手把手教你用Verilog在FPGA上构建自己的FFT处理器(不依赖IP核)

本文详细介绍了如何从零开始使用Verilog在FPGA上构建256点FFT处理器,不依赖商业IP核。内容涵盖FFT算法基础、蝶形运算单元设计、整体架构实现、时序收敛优化策略以及测试验证方法,重点提升FPGA上算法部署的运行效率与资源利用率。

vv45678的博客 821

安卓页面绘制流程(3)Window注册

主要介绍Window和DecorView等涉及到页面展示的关键对象是如何创建的,这些主要发生在create Activity的流程中。

分享+记录 1365

别再到处找了!GWAS数据下载保姆级指南:从IEU、FinnGen到UK Biobank一站搞定

本文提供GWAS数据下载的全面指南,涵盖IEU OpenGWAS、FinnGen、UK Biobank等五大核心数据库的获取策略。从数据库选型到实战操作,详细解析数据搜索、下载、预处理全流程,帮助科研人员高效获取GWAS数据,特别适合初学者快速上手。

weixin_42523543的博客 1581

四足机器人关节电机FOC控制实战:从磁编码器校准到SVPWM调试避坑指南

本文详细解析了四足机器人关节电机FOC控制实战,涵盖磁编码器校准、电流环调试和SVPWM波形优化等关键环节。通过MIT Cheetah案例展示如何解决21倍电气误差问题,并提供相序自动校正、PI参数整定等实用代码片段,帮助工程师避开永磁同步电机(PMSM)控制中的常见陷阱。

weixin_29281915的博客 489

Android窗口层级(Window Type)分析

车载方案存在倒车等特殊界面需要在较高的窗口层级显示,Android原有的窗口层级不满足车载需求,因此都会自定义车载窗口层级。下图为参考自定义的窗口层级:android自定义窗口层级(自定义车载系统中倒车影像显示层级)自定义窗口层级在不同Android版本中的初始层级值也是不同,因此需要通过系统属性来判断初始值。例如在Android 13平台的默认属性为2401,在Andoid 9等平台为2031。这样做的目的是由于跟Android原生的窗口层级存在冲突,因此需要根据平台来调节初始值。

分享技术与经验的博客 1万+

易康eCognition9.0分类|规则集和机器学习的方法的面向对象的多尺度分割分类

基于易康eCognition9.0软件的规则集和机器学习的方法的面向对象的多尺度分割分类

weixin_46493028的博客 1万+

Android如何获window对象,Android Window机制

Window的简单使用public void addView(View view){mFloatingButton = new Button(this);mFloatingButton.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {...

weixin_35919843的博客 3541

Windows 下安装 ros2 的超详细教程

Windows11 ROS安装

2401_83363439的博客 3316

OpenCV入门(一)Python环境的搭建

因为有点Python基础,并且Python是比较好入门的编程语言,所以,机器视觉后面打算在Python这个平台下进行。

小幽余生不加糖 8117

android获取当前windows,Android 中的 Window

一台 Android 手机屏幕上显示的内容就是由一个个 Window 组合而成的。顶部的状态栏是一个 Window,底部的导航栏也是一个 Window,中间自己的应用显示区域也是一块大 Window,Toast、Dialog 也都对应一个自己的 Window。而 Android 中对这些 Window 的管理是通过 一个框架的服务,叫 WMS(WindowManagerService)。这些 Wi...

weixin_39929723的博客 2369

遥感图像地物覆盖分类,数据集制作-分类模型对比-分类保姆级教程

1.新建shp文件地理坐标系保持和影像一致,面类型2.打开属性表3.添加字段这里分类6类,点击添加值添加添加完毕开始人工选地物类型,制作数据集开始标注,标注的时候可以借助谷歌地图来看标记足够多的样本打开面转栅格工具设置nodata值为15。

热爱分享,热爱记录 2524

Android的Window底层原理

1.概述  Window是一个抽象类,他的实现是PhoneWindow。Window通过WindowManager创建,是访问Window的入口。Window的具体实现位于WindowManagerService中,WIndowManager与WindowManagerService的交互是一个IPC的过程。 WindowManager中的Layoutparam中的Type表示Window的类

黄俊彬 3434

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Android 12 S WindowManager解读之从dumpsys window windows看window

();;();;();执行adb shell dumpsys window windows 如下:rootTaskId=1(根Taskid) mSession=Session{e98843e 2512:u0a10120} mClient=android.os.BinderProxy@64c3da9appop=NONEmcc?mcc?

weixin_41028555的博客 4857

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

【Android】Window 机制

Window,即窗口,在 Android 中,它是一个抽象的东西,我们在日常开发中,直接接触到的东西是 View,而 View 是附着在 Window 之上的。所以我们也可以说 Window 是 View 的直接管理者。在了解 window 机制之前,我们需要对 Android 系统中的显示部分涉及到的东西有一个大致的了解。

yang553566463的博客 2406

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

上一篇: 卡片式ViewPager,一屏展示多个pager item,设置高度不一致的tabBar
下一篇: Python中TypeError: object() takes no parameters问题
MrCoderr
博客等级 码龄12年 39粉丝 48原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值