理解Android中不同的Context

news2024/12/26 23:04:15

作者:两日的blog

Context是什么,有什么用

在Android开发中,Context是一个抽象类,它是Android应用程序环境的一部分。它提供了访问应用程序资源和执行各种操作的接口。可以说,Context是Android应用程序与系统环境进行交互的桥梁

Context的作用包括:

  1. 访问应用程序资源:通过Context,可以获取应用程序的资源,如字符串、布局文件、图像等。这些资源可以在应用程序的各个组件中使用,例如ActivityServiceBroadcastReceiver等。
  2. 启动组件:通过Context,可以启动其他组件,如启动Activity、启动Service、发送广播等。它提供了访问系统服务的能力,如启动其他应用程序、发送系统广播等。
  3. 获取应用程序的上下文:通过Context,可以获取应用程序的上下文,如获取ApplicationContext,用于在整个应用程序中共享数据或执行全局操作。
  4. 访问系统服务:通过Context,可以访问各种系统服务,如获取系统级的服务(如传感器服务、位置服务)、访问设备功能(如摄像头、存储器)、执行网络操作等。
  5. 访问应用程序的文件:通过Context对象,可以获取应用程序的文件目录,创建、读取、写入和删除文件等操作。
  6. 处理资源生命周期:通过Context,可以管理应用程序资源的生命周期,如创建、销毁对象、注册和注销监听器等。它提供了一种机制,确保资源的正确使用和释放,避免内存泄漏等问题。
public abstract AssetManager getAssets();

/**
 * Returns a Resources instance for the application's package.
 * <p>
 * <strong>Note:</strong> Implementations of this method should return
 * a Resources instance that is consistent with the AssetManager instance
 * returned by {@link #getAssets()}. For example, they should share the
 * same {@link Configuration} object.
 *
 * @return a Resources instance for the application's package
 * @see #getAssets()
 */
public abstract Resources getResources();

/** Return PackageManager instance to find global package information. */
public abstract PackageManager getPackageManager();

/** Return a ContentResolver instance for your application's package. */
public abstract ContentResolver getContentResolver();

/**
 * Return the Looper for the main thread of the current process.  This is
 * the thread used to dispatch calls to application components (activities,
 * services, etc).
 * <p>
 * By definition, this method returns the same result as would be obtained
 * by calling {@link Looper#getMainLooper() Looper.getMainLooper()}.
 * </p>
 *
 * @return The main looper.
 */
public abstract Looper getMainLooper();

/**
 * Return an {@link Executor} that will run enqueued tasks on the main
 * thread associated with this context. This is the thread used to dispatch
 * calls to application components (activities, services, etc).
 */
public Executor getMainExecutor() {
    // This is pretty inefficient, which is why ContextImpl overrides it
    return new HandlerExecutor(new Handler(getMainLooper()));
}

 
public abstract Context getApplicationContext();

public final CharSequence getText(@StringRes int resId) {
    return getResources().getText(resId);
}

/**
 * Returns a localized string from the application's package's
 * default string table.
 *
 * @param resId Resource id for the string
 * @return The string data associated with the resource, stripped of styled
 *         text information.
 */
@NonNull
public final String getString(@StringRes int resId) {
    return getResources().getString(resId);
}

/**
 * Returns a localized formatted string from the application's package's
 * default string table, substituting the format arguments as defined in
 * {@link java.util.Formatter} and {@link java.lang.String#format}.
 *
 * @param resId Resource id for the format string
 * @param formatArgs The format arguments that will be used for
 *                   substitution.
 * @return The string data associated with the resource, formatted and
 *         stripped of styled text information.
 */
@NonNull
public final String getString(@StringRes int resId, Object... formatArgs) {
    return getResources().getString(resId, formatArgs);
}

/**
 * Returns a color associated with a particular resource ID and styled for
 * the current theme.
 *
 * @param id The desired resource identifier, as generated by the aapt
 *           tool. This integer encodes the package, type, and resource
 *           entry. The value 0 is an invalid identifier.
 * @return A single color value in the form 0xAARRGGBB.
 * @throws android.content.res.Resources.NotFoundException if the given ID
 *         does not exist.
 */
@ColorInt
public final int getColor(@ColorRes int id) {
    return getResources().getColor(id, getTheme());
}

/**
 * Returns a drawable object associated with a particular resource ID and
 * styled for the current theme.
 *
 * @param id The desired resource identifier, as generated by the aapt
 *           tool. This integer encodes the package, type, and resource
 *           entry. The value 0 is an invalid identifier.
 * @return An object that can be used to draw this resource.
 * @throws android.content.res.Resources.NotFoundException if the given ID
 *         does not exist.
 */
@Nullable
public final Drawable getDrawable(@DrawableRes int id) {
    return getResources().getDrawable(id, getTheme());
}

/**
 * Returns a color state list associated with a particular resource ID and
 * styled for the current theme.
 *
 * @param id The desired resource identifier, as generated by the aapt
 *           tool. This integer encodes the package, type, and resource
 *           entry. The value 0 is an invalid identifier.
 * @return A color state list.
 * @throws android.content.res.Resources.NotFoundException if the given ID
 *         does not exist.
 */
@NonNull
public final ColorStateList getColorStateList(@ColorRes int id) {
    return getResources().getColorStateList(id, getTheme());
}

 /**
 * Set the base theme for this context.  Note that this should be called
 * before any views are instantiated in the Context (for example before
 * calling {@link android.app.Activity#setContentView} or
 * {@link android.view.LayoutInflater#inflate}).
 *
 * @param resid The style resource describing the theme.
 */
public abstract void setTheme(@StyleRes int resid);

/** @hide Needed for some internal implementation...  not public because
 * you can't assume this actually means anything. */
@UnsupportedAppUsage
public int getThemeResId() {
    return 0;
}

/**
 * Return the Theme object associated with this Context.
 */
@ViewDebug.ExportedProperty(deepExport = true)
public abstract Resources.Theme getTheme();

/**
 * Retrieve styled attribute information in this Context's theme.  See
 * {@link android.content.res.Resources.Theme#obtainStyledAttributes(int[])}
 * for more information.
 *
 * @see android.content.res.Resources.Theme#obtainStyledAttributes(int[])
 */
@NonNull
public final TypedArray obtainStyledAttributes(@NonNull @StyleableRes int[] attrs) {
    return getTheme().obtainStyledAttributes(attrs);
}

/**
 * Retrieve styled attribute information in this Context's theme.  See
 * {@link android.content.res.Resources.Theme#obtainStyledAttributes(int, int[])}
 * for more information.
 *
 * @see android.content.res.Resources.Theme#obtainStyledAttributes(int, int[])
 */
@NonNull
public final TypedArray obtainStyledAttributes(@StyleRes int resid,
        @NonNull @StyleableRes int[] attrs) throws Resources.NotFoundException {
    return getTheme().obtainStyledAttributes(resid, attrs);
}

/**
 * Retrieve styled attribute information in this Context's theme.  See
 * {@link android.content.res.Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}
 * for more information.
 *
 * @see android.content.res.Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
 */
@NonNull
public final TypedArray obtainStyledAttributes(
        @Nullable AttributeSet set, @NonNull @StyleableRes int[] attrs) {
    return getTheme().obtainStyledAttributes(set, attrs, 0, 0);
}

/**
 * Retrieve styled attribute information in this Context's theme.  See
 * {@link android.content.res.Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}
 * for more information.
 *
 * @see android.content.res.Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
 */
@NonNull
public final TypedArray obtainStyledAttributes(@Nullable AttributeSet set,
        @NonNull @StyleableRes int[] attrs, @AttrRes int defStyleAttr,
        @StyleRes int defStyleRes) {
    return getTheme().obtainStyledAttributes(
        set, attrs, defStyleAttr, defStyleRes);
}

总之,Context在Android开发中具有重要的作用,它提供了访问应用程序资源、启动组件、访问系统服务以及处理资源生命周期的能力。开发者可以使用Context来实现各种应用程序功能和与系统环境的交互。

Context有哪些

Context 本身是一个抽象类,主要实现类为 ContextImpl,另外有子类 ContextWrapperContextThemeWrapper,另外还有其他由上述三个类引申出来的Context类,Application/Service/Activity,他们的继承关系如下:

ContextImpl/ContextWrapper/ContextThemeWrapper的区别

ContextImplContextWrapperContextThemeWrapper
ContextImplContext的主要实现类,它提供了大部分Context的基本功能和行为。它是Android框架中真正的上下文实现类,用于处理应用程序的资源访问、组件启动、文件操作和系统服务等操作。ContextWrapper是一个包装类,用于对现有的Context对象进行包装或修改其功能。它是Context的一个间接子类,可以通过继承ContextWrapper类来扩展Context的功能,例如添加自定义的行为或修改Context的行为。ContextThemeWrapperContextThemeWrapperContext的另一个包装类,它继承自ContextWrapper类。与ContextWrapper类似,ContextThemeWrapper也是用于包装现有的Context对象,但它还提供了自己的主题资源。通过ContextThemeWrapper,可以为特定的上下文设置不同的主题,以实现界面的样式和外观的变化。

ContextImpl

上文说到,Context本身是一个抽象类,主要的实现类就是ContextImpl,即Context的那些功能都是在ContexImpl中实现的,即ContextImpl实际承担着提供应用程序资源访问、组件启动和系统服务等功能的责任。

public class ContextImpl extends Context {
    private Resources mResources;
    private Theme mTheme;
   
    void setResources(Resources r) {
        if (r instanceof CompatResources) {
            ((CompatResources) r).setContext(this);
        }
        mResources = r;
    }
    
    @Override
    public Resources getResources() {
        return mResources;
    }
    
    @Override
    public void setTheme(int resId) {
        synchronized (mSync) {
            if (mThemeResource != resId) {
                mThemeResource = resId;
                initializeTheme();
            }
        }
    }
    
    public Resources.Theme getTheme() {
        synchronized (mSync) {
            if (mTheme != null) {
                return mTheme;
            }
    
            mThemeResource = Resources.selectDefaultTheme(mThemeResource,
                    getOuterContext().getApplicationInfo().targetSdkVersion);
            initializeTheme();
    
            return mTheme;
        }
    }
    
    private void initializeTheme() {
        if (mTheme == null) {
            mTheme = mResources.newTheme();
        }
        mTheme.applyStyle(mThemeResource, true);
    }
    
    // 其他方法的实现省略...
}

ContextImpl,我们重点关注一下ResourceTheme的相关实现,ContextImpl中提供了getResources/setResources方法,用于获取Resources以及设置Resources,以提供资源的访问。

getTheme/setTheme用于获取Theme以及设置Theme,以提供对主题的访问.

重点看一下getTheme()方法,该方法,会首先获取mThemeResource,这里直接选择的系统默认主题,系统会根据不同的sdk版本选择不同的默认主题。

@UnsupportedAppUsage
public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
    return selectSystemTheme(curTheme, targetSdkVersion,
            com.android.internal.R.style.Theme,
            com.android.internal.R.style.Theme_Holo,
            com.android.internal.R.style.Theme_DeviceDefault,
            com.android.internal.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}

/** @hide */
public static int selectSystemTheme(int curTheme, int targetSdkVersion, int orig, int holo,
        int dark, int deviceDefault) {
    if (curTheme != ID_NULL) {
        return curTheme;
    }
    if (targetSdkVersion < Build.VERSION_CODES.HONEYCOMB) {
        return orig;
    }
    if (targetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        return holo;
    }
    if (targetSdkVersion < Build.VERSION_CODES.N) {
        return dark;
    }
    return deviceDefault;
}

通过ContextImpl的实例,应用程序可以获取到Resources对象和Theme对象,从而实现对资源和主题的访问和处理。需要注意的是,这是一个简化的,实际的ContextImpl源码非常复杂,还涉及到处理上下文的生命周期、系统服务的获取等方面的逻辑。

ContextWrapper

ContextWrapper是一个包装类,内部包含一个mBase成员变量,所有的实现都是调用mBase的方法。

public class ContextWrapper extends Context {
    @UnsupportedAppUsage
    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }
    
    @Override
    public void setTheme(int resid) {
        mBase.setTheme(resid);
    }
    
    /** @hide */
    @Override
    @UnsupportedAppUsage
    public int getThemeResId() {
        return mBase.getThemeResId();
    }
    
    @Override
    public Resources.Theme getTheme() {
        return mBase.getTheme();
    }
    
    @Override
    public ClassLoader getClassLoader() {
        return mBase.getClassLoader();
    }
    
    @Override
    public String getPackageName() {
        return mBase.getPackageName();
    }
    
 }

ContextThemeWrapper

ContextThemeWrapper继承自ContextWrapper,从名字中可以看出,该类主要是跟主题相关的包装类:

public class ContextThemeWrapper extends ContextWrapper {
    ...
    
    @Override
    public Resources getResources() {
        return getResourcesInternal();
    }
    
    private Resources getResourcesInternal() {
        if (mResources == null) {
            if (mOverrideConfiguration == null) {
                mResources = super.getResources();
            } else {
                final Context resContext = createConfigurationContext(mOverrideConfiguration);
                mResources = resContext.getResources();
            }
        }
        return mResources;
    }
    
    @Override
    public void setTheme(int resid) {
        if (mThemeResource != resid) {
            mThemeResource = resid;
            initializeTheme();
        }
    }
    
    @Override
    public Resources.Theme getTheme() {
        if (mTheme != null) {
            return mTheme;
        }
    
        mThemeResource = Resources.selectDefaultTheme(mThemeResource,
                getApplicationInfo().targetSdkVersion);
        initializeTheme();
    
        return mTheme;
    }
    
    @UnsupportedAppUsage
    private void initializeTheme() {
        final boolean first = mTheme == null;
        if (first) {
            mTheme = getResources().newTheme();
            final Resources.Theme theme = getBaseContext().getTheme();
            if (theme != null) {
                mTheme.setTo(theme);
            }
        }
        onApplyThemeResource(mTheme, mThemeResource, first);
    }
    
    ...

}

ContextImpl相比较,ContextThemeWrapper中获取资源以及主题的代码有所不同,多了一个Configuration,其他行为大致一致。

另外在AppCompat中,默认的主题为Theme_AppCompat_Light

package androidx.appcompat.view;

public class ContextThemeWrapper extends ContextWrapper {
    ... 
    @Override
    public Resources.Theme getTheme() {
        if (mTheme != null) {
            return mTheme;
        }
    
        if (mThemeResource == 0) {
            mThemeResource = R.style.Theme_AppCompat_Light;
        }
        initializeTheme();
    
        return mTheme;
    }
}

App中不同Context对象的Theme

我们在开发中,经常会用到各种Context,常用的有activity/application/applicationContext/baseContext,为了测试不同Context中Theme对象,我们编写如下代码:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        printLog("baseContext is ${baseContext.themeResId} baseContext is $baseContext")
        printLog("application is ${application.themeResId} application is $application")
        printLog("applicationContext is ${applicationContext.themeResId} applicationContext is $applicationContext")
        printLog("activity is ${this.themeResId}")

    }

    private fun printLog(msg: String) {
        println("MainActivity themeResId in $msg")
    }
}

我们分别获取每个Context对应的themeResId,即每个ContextTheme对应的resId

对代码运行结果我们有如下结论:

  1. getApplicationgetApplicationContext得到的是同一个Application实例对象;
  2. Application对象中的themeResId 为0 ,Application其实也有主题的应用,毕竟主题样式都是针对UI元素的;
  3. **Activity中的主题和getBaseContext**中的主题是不一样的,具体对应什么主题下文将进行探究
  4. getBaseContext中得到的是ContextThemeWrapper,这点让我有点意外,之前的理解都是Activity启动时,会新建一个ContextImpl对象,在attachBaseContext中赋予Activity中的mBase,于是仔细研究一下发现,其实是AppCompatActivity做了替换:
//androidx.appcompat.app.AppCompatActivity
// AppCompatActivity重写了Activity中的attachBaseContext方法
@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(getDelegate().attachBaseContext2(newBase));
}

我们看一下代理类AppCompatDelegateImplattachBaseContext2的实现:

//androidx.appcompat.app.AppCompatDelegateImpl

@NonNull
@Override
@CallSuper
public Context attachBaseContext2(@NonNull final Context baseContext) {
    mBaseContextAttached = true;

    final int modeToApply = mapNightMode(baseContext, calculateNightMode());

    // If the base context is a ContextThemeWrapper (thus not an Application context)
    // and nobody's touched its Resources yet, we can shortcut and directly apply our
    // override configuration.
    if (sCanApplyOverrideConfiguration
            && baseContext instanceof android.view.ContextThemeWrapper) {
        final Configuration config = createOverrideConfigurationForDayNight(
                baseContext, modeToApply, null);

        ContextThemeWrapperCompatApi17Impl.applyOverrideConfiguration(
                (android.view.ContextThemeWrapper) baseContext, config);
        return baseContext;
        
    }

    // Again, but using the AppCompat version of ContextThemeWrapper.
    if (baseContext instanceof ContextThemeWrapper) {
        final Configuration config = createOverrideConfigurationForDayNight(
                baseContext, modeToApply, null);
        
        ((ContextThemeWrapper) baseContext).applyOverrideConfiguration(config);
        return baseContext;
        
    }

    // We can't apply the configuration directly to the existing base context, so we need to
    // wrap it. We can't create a new configuration context since the app may rely on method
    // overrides or a specific theme -- neither of which are preserved when creating a
    // configuration context. Instead, we'll make a best-effort at wrapping the context and
    // rebasing the original theme.
    if (!sCanReturnDifferentContext) {
        return super.attachBaseContext2(baseContext);
    }

    Configuration configOverlay = null;

    final Configuration config = createOverrideConfigurationForDayNight(
            baseContext, modeToApply, configOverlay);
  
      //重点1:新建ContextThemeWrapper对象将传入的baseContext赋值给ContextWrapper中的mBase,
      // 并且ContextThemeWrapper中的主题为Theme_AppCompat_Empty
    // Next, we'll wrap the base context to ensure any method overrides or themes are left
    // intact. Since ThemeOverlay.AppCompat theme is empty, we'll get the base context's theme.
    final ContextThemeWrapper wrappedContext = new ContextThemeWrapper(baseContext,
            R.style.Theme_AppCompat_Empty);
    wrappedContext.applyOverrideConfiguration(config);

    // Check whether the base context has an explicit theme or is able to obtain one
    // from its outer context. If it throws an NPE because we're at an invalid point in app
    // initialization, we don't need to worry about rebasing under the new configuration.
    boolean needsThemeRebase;
    try {
        needsThemeRebase = baseContext.getTheme() != null;
    } catch (NullPointerException e) {
        needsThemeRebase = false;
    }

    if (needsThemeRebase) {
        // Attempt to rebase the old theme within the new configuration. This will only
        // work on SDK 23 and up, but it's unlikely that we're keeping the base theme
        // anyway so maybe nobody will notice. Note that calling getTheme() will clone
        // the base context's theme into the wrapped context's theme.
        ResourcesCompat.ThemeCompat.rebase(wrappedContext.getTheme());
    }

    
    return super.attachBaseContext2(wrappedContext);
}

//androidx.appcompat.app.AppCompatDelegate
@NonNull
@CallSuper
public Context attachBaseContext2(@NonNull Context context) {
// 重点2,将上一步包装了baseContext的ContextThemeWrapper对象进一步赋值给Activity的mBase
    attachBaseContext(context);
    return context;
}

最终AppCompatActivity中的mBase是包装了ContextImplContextThemeWrapper对象,并且其主题为Theme_AppCompat_Empty

关于第三点,getBaseActivityActivity中的主题到底是哪一个,我们可以根据resId和resources索引表resource.arsc(直接将apk文件拖到AndroidStudio中就可以看到该文件)找到:

21317554102131755474对应16进制为0x7f1001920x7f1001d2

可以看到,getBaseActivityActivity中的主题分别对应Theme_AppCompat_Empty 与我们在AndroidManifest.xml中设置的应用主题Theme.ThemeTest

总结

Context是Android应用程序与系统环境进行交互的桥梁,主要实现类是ContextImpl, 可以访问应用程序资源/启动组件/访问系统服务/访问应用程序的文件等,而Context可以分为三种:ContextImpl/ContextWrapper/ContextThemeWrapper,不同ContextImpl 是Context的主要实现类,ContextWrapper是简单的包装类,所有的实现都由其内部的mBase成员完成,ContextThemeWrapper继承自ContextWrapper ,它的主要继承者是Activity,和其他两个Context不同的是,他内部对应用资源和主题有不同的行为,在应用中使用跟主题相关的Context时,最好使用activity,而不要使用getBaseContext或者applictaion.

Android 学习笔录

Android 性能优化篇:https://qr18.cn/FVlo89
Android 车载篇:https://qr18.cn/F05ZCM
Android 逆向安全学习笔记:https://qr18.cn/CQ5TcL
Android Framework底层原理篇:https://qr18.cn/AQpN4J
Android 音视频篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(内含Compose):https://qr18.cn/A0gajp
Kotlin 篇:https://qr18.cn/CdjtAF
Gradle 篇:https://qr18.cn/DzrmMB
OkHttp 源码解析笔记:https://qr18.cn/Cw0pBD
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知识体:https://qr18.cn/CyxarU
Android 核心笔记:https://qr21.cn/CaZQLo
Android 往年面试题锦:https://qr18.cn/CKV8OZ
2023年最新Android 面试题集:https://qr18.cn/CgxrRy
Android 车载开发岗位面试习题:https://qr18.cn/FTlyCJ
音视频面试题锦:https://qr18.cn/AcV6Ap

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/796201.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LoadRunner使用教程

1. LoadRunner简介 LoadRunner是一款广泛使用的性能测试工具 可以对各种应用程序进行性能测试&#xff0c;包括Web应用程序、移动应用程序、企业级应用程序等。它提供了一个综合的性能测试解决方案&#xff0c;包括测试计划设计、脚本录制、测试执行、结果分析和报告生成等功…

三、函数-5.流程函数

一、常见函数 【对比】 二、示例 1、if 和 ifnull -- if(value, t, f) 如果value为true&#xff0c;则返回t&#xff0c;否则返回f ok select if(true, ok, error);-- ifnull(value1, value2) 如果value1不为空&#xff0c;返回value1&#xff0c;否则返回value2&#…

MFC表格控件CListCtrl的改造及用法

1、目的 简单描述MFC的表格控件使用方法。Qt适用习惯了以后MFC用的比较别扭&#xff0c;因此记录一下以备后续复制代码使用。由于MFC原生的CListCtrl比较局限&#xff0c;比如无法改变表格的背景色、文字颜色等设定&#xff0c;因此先对CListCtrl类进行重写&#xff0c;以便满足…

哪些报表工具更适合中国企业?看完本文就知道了

企业级报表工具是指能够处理大量数据、支持多种数据源连接、具有强大的数据分析和可视化功能的工具。进入大数据时代&#xff0c;企业数据量剧增、分析需求精细化且要求高效率、高灵活自主性&#xff0c;一般都采用BI报表工具来做智能化、可视化数据分析&#xff0c;推动企业的…

Neo4j数据库中导入CSV示例数据

本文简要介绍Neo4j数据库以及如何从CSV文件中导入示例数据&#xff0c;方便我们快速学习测试图数据库。首先介绍简单数据模型以及基本图查询概念&#xff0c;然后通过LOAD CSV命令导入数据&#xff0c;生成节点和关系。 环境准备 读者可以快速安装Neo4j Desktop&#xff0c;启…

Mysql中(@i:=@i+1)的介绍

i:i1 表达式 生成伪列实现自增序列 语法&#xff1a; select (i:i1) as ,t.* from table_name t,(select i:0) as j (i:i1)代表定义一个变量&#xff0c;每次叠加 1&#xff1b; (select i:0) as j 代表建立一个临时表&#xff0c;j是随便取的表名&#xff0c;但别名一定…

python和c++哪个更值得学,python和c++学哪个简单

大家好&#xff0c;本文将围绕python和c哪个更值得学展开说明&#xff0c;python和c学哪个简单是一个很多人都想弄明白的事情&#xff0c;想搞清楚c和python哪个好学需要先了解以下几个事情。 1、想学编程&#xff0c;选择Python 还是Java或者C&#xff1f; 首先&#xff0c;我…

MySQL索引失效原因及解决方案

MySQL索引失效原因及解决方案 在使用MySQL数据库时&#xff0c;索引是一种重要的性能优化工具。然而&#xff0c;有时候我们可能会遇到索引失效的情况。本文将介绍几种常见的MySQL索引失效原因以及相应的解决方案&#xff0c;并提供SQL语句的错误示例和正确示例。 1. 字符串字…

HarmonyOS学习路之方舟开发框架—学习ArkTS语言(状态管理 二)

Prop装饰器&#xff1a;父子单向同步 Prop装饰的变量可以和父组件建立单向的同步关系。Prop装饰的变量是可变的&#xff0c;但是变化不会同步回其父组件。 概述 Prop装饰的变量和父组件建立单向的同步关系&#xff1a; Prop变量允许在本地修改&#xff0c;但修改后的变化不会…

tinkerCAD案例:11.制作齿轮

tinkerCAD案例&#xff1a;11.制作齿轮 制作齿轮 Add a cylinder to be the main part of the gear. 添加一个圆柱体作为齿轮的主要部分。 说明 Click and drag a cylinder onto the Workplane. 单击圆柱体并将其拖动到工作平面上。 Change the cylinder dimensions to 35mm …

四、约束-1.概述

一、概念 约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。 二、目的 保证数据库中数据的正确、有效性和完整性。 三、分类

视觉套件专项活动!与飞桨技术专家一起提升技术实力,更多荣誉奖励等你领取

作为中国最早开源的深度学习框架&#xff0c;飞桨深度践行开源理念&#xff0c;开放拥抱社区&#xff0c;重视生态构建&#xff0c;与开发者和生态伙伴共成长&#xff0c;已成为国内综合竞争力第一的产业级深度学习平台。截至目前&#xff0c;飞桨已凝聚750万名开发者。 在飞桨…

i.MX6ULL(十九) linux gpio子系统

一 简介 pinctrl 子系统重点是设置 PIN( 有的 SOC 叫做 PAD) 的复用 和电气属性&#xff0c; 如果 pinctrl 子系统将一个 PIN 复用为 GPIO 的话&#xff0c;那么接下来就要用到 gpio 子系 统了。gpio 子系统顾名思义&#xff0c;就是用于初始化 GPIO 并且提供相…

idea,选中同一个变量高亮显示

阅读复杂代码时&#xff0c;我们经常因为找不清变量位置&#xff0c;而浪费精力重新去看变量名。 效果展示&#xff1a; 在设置里直接搜索按照步骤&#xff0c;勾选然后修改选中变量时的变量背景颜色和字体颜色 这里是设置选中变量时&#xff0c;其他变量的背景颜色和字体颜色…

终于搞懂!数字化、信息化、智能化,到底有什么不同?

引言 随着科技的飞速发展&#xff0c;数字化、信息化和智能化这三个术语在各行各业中频繁出现。然而&#xff0c;许多人对它们之间的区别并不十分清楚。本文旨在阐明数字化、信息化和智能化的含义&#xff0c;探讨它们在实践中的应用&#xff0c;并梳理其异同之处。 一、数字化…

你不知道的AI绘画变现方式

&#x1f3c6; 文章目标&#xff1a;学习AI绘画变现方式 &#x1f340; 入门篇&#xff1a;你不知道的AI绘画变现方式 ✅ 创作者&#xff1a;熊猫Jay ✨ 个人公众号: 熊猫Jay字节之旅 (文末有链接) &#x1f341; 展望&#xff1a;若本篇讲解内容帮助到您&#xff0c;请帮忙点个…

【科研必备】生态系统碳循环模型CENTURY建模方法

CENTURY模型&#xff0c;主要基于过程的陆地生态系统生物地球化学循环模型。主要用于模拟不同土壤-植被系统间C、N、P和S的长期动态。根据土壤有机质的分解速率&#xff0c;CENTURY模型将土壤总有机碳&#xff08;TOC&#xff09;分成了三个碳库&#xff0c;即活性、慢性和惰性…

Rest API 开发分享

概述 REST 从资源的角度来观察整个网络&#xff0c;分布在各处的资源由URI确定&#xff0c;而客户端的应用通过URI来获取资源的表示方式。获得这些表徵致使这些应用程序转变了其状态。随着不断获取资源的表示方式&#xff0c;客户端应用不断地在转变着其状态&#xff0c;所谓表…

js获取本js文件名称

使用 script 标签的 src 属性&#xff1a; 如果您的 JavaScript 文件是通过 script 标签引入的&#xff0c;您可以使用以下方法来获取当前脚本的文件名&#xff1a; var scripts document.getElementsByTagName(script); var currentScript scripts[scripts.length - 1]; va…

CMU 15-445 -- Multi-Version Concurrency Control - 16

CMU 15-445 -- Multi-Version Concurrency Control - 16 引言MVCCExample #1Example #2小结 Design DecisionsConcurrency Control ProtocolVersion StorageAppend-Only StorageTime-Travel StorageDelta Storage Garbage CollectionTuple-Level GCTransaction-Level GC Index …