gpt4 book ai didi

java - 为什么 ContextThemeWrapper 会覆盖 ContextWrapper 中定义的字段 "mBase"?

转载 作者:行者123 更新时间:2023-11-29 09:06:03 27 4
gpt4 key购买 nike

我是java初学者。现在正在学习android开发,对android.view.ContextThemeWrapper类的定义很疑惑。它是 android.content.ContextWrapper 的子类。这两个类都包含一个字段 mBase(和 android.content.Context 的实例)。在基类中,它声明没有访问修饰符,但在子类中它声明了私有(private)修饰符。

所以android.view.ContextThemeWrapper的一个实例确实有两个名为“mBase”的字段,只有在派生部分定义的是可见的,但是在基类部分声明的是隐藏的。为什么在这里派生类的实例中需要两份“mBase”字段?在哪种情况下,我应该将基类中定义的字段覆盖为私有(private)字段?

我需要你的帮助。提前致谢。

下面是两个类的定义:

android.content.ContextWrapper:

 /**
* Proxying implementation of Context that simply delegates all of its calls to
* another Context. Can be subclassed to modify behavior without changing
* the original Context.
*/
public class ContextWrapper extends Context {
Context mBase;

public ContextWrapper(Context base) {
mBase = base;
}

/**
* Set the base context for this ContextWrapper. All calls will then be
* delegated to the base context. Throws
* IllegalStateException if a base context has already been set.
*
* @param base The new base context for this wrapper.
*/
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}

/**
* @return the base context as set by the constructor or setBaseContext
*/
public Context getBaseContext() {
return mBase;
}

@Override
public AssetManager getAssets() {
return mBase.getAssets();
}

@Override
public Resources getResources()
{
return mBase.getResources();
}

@Override
public PackageManager getPackageManager() {
return mBase.getPackageManager();
}

@Override
public ContentResolver getContentResolver() {
return mBase.getContentResolver();
}

@Override
public Looper getMainLooper() {
return mBase.getMainLooper();
}

@Override
public Context getApplicationContext() {
return mBase.getApplicationContext();
}

@Override
public void setTheme(int resid) {
mBase.setTheme(resid);
}

/** @hide */
@Override
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();
}

@Override
public ApplicationInfo getApplicationInfo() {
return mBase.getApplicationInfo();
}

@Override
public String getPackageResourcePath() {
return mBase.getPackageResourcePath();
}

@Override
public String getPackageCodePath() {
return mBase.getPackageCodePath();
}

/** @hide */
@Override
public File getSharedPrefsFile(String name) {
return mBase.getSharedPrefsFile(name);
}

@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
return mBase.getSharedPreferences(name, mode);
}

@Override
public FileInputStream openFileInput(String name)
throws FileNotFoundException {
return mBase.openFileInput(name);
}

@Override
public FileOutputStream openFileOutput(String name, int mode)
throws FileNotFoundException {
return mBase.openFileOutput(name, mode);
}

@Override
public boolean deleteFile(String name) {
return mBase.deleteFile(name);
}

@Override
public File getFileStreamPath(String name) {
return mBase.getFileStreamPath(name);
}

@Override
public String[] fileList() {
return mBase.fileList();
}

@Override
public File getFilesDir() {
return mBase.getFilesDir();
}

@Override
public File getExternalFilesDir(String type) {
return mBase.getExternalFilesDir(type);
}

@Override
public File getObbDir() {
return mBase.getObbDir();
}

@Override
public File getCacheDir() {
return mBase.getCacheDir();
}

@Override
public File getExternalCacheDir() {
return mBase.getExternalCacheDir();
}

@Override
public File getDir(String name, int mode) {
return mBase.getDir(name, mode);
}

@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
return mBase.openOrCreateDatabase(name, mode, factory);
}

@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
DatabaseErrorHandler errorHandler) {
return mBase.openOrCreateDatabase(name, mode, factory, errorHandler);
}

@Override
public boolean deleteDatabase(String name) {
return mBase.deleteDatabase(name);
}

@Override
public File getDatabasePath(String name) {
return mBase.getDatabasePath(name);
}

@Override
public String[] databaseList() {
return mBase.databaseList();
}

@Override
public Drawable getWallpaper() {
return mBase.getWallpaper();
}

@Override
public Drawable peekWallpaper() {
return mBase.peekWallpaper();
}

@Override
public int getWallpaperDesiredMinimumWidth() {
return mBase.getWallpaperDesiredMinimumWidth();
}

@Override
public int getWallpaperDesiredMinimumHeight() {
return mBase.getWallpaperDesiredMinimumHeight();
}

@Override
public void setWallpaper(Bitmap bitmap) throws IOException {
mBase.setWallpaper(bitmap);
}

@Override
public void setWallpaper(InputStream data) throws IOException {
mBase.setWallpaper(data);
}

@Override
public void clearWallpaper() throws IOException {
mBase.clearWallpaper();
}

@Override
public void startActivity(Intent intent) {
mBase.startActivity(intent);
}

/** @hide */
@Override
public void startActivityAsUser(Intent intent, UserHandle user) {
mBase.startActivityAsUser(intent, user);
}

@Override
public void startActivity(Intent intent, Bundle options) {
mBase.startActivity(intent, options);
}

/** @hide */
@Override
public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
mBase.startActivityAsUser(intent, options, user);
}

@Override
public void startActivities(Intent[] intents) {
mBase.startActivities(intents);
}

@Override
public void startActivities(Intent[] intents, Bundle options) {
mBase.startActivities(intents, options);
}

/** @hide */
@Override
public void startActivitiesAsUser(Intent[] intents, Bundle options, UserHandle userHandle) {
mBase.startActivitiesAsUser(intents, options, userHandle);
}

@Override
public void startIntentSender(IntentSender intent,
Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
throws IntentSender.SendIntentException {
mBase.startIntentSender(intent, fillInIntent, flagsMask,
flagsValues, extraFlags);
}

@Override
public void startIntentSender(IntentSender intent,
Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
Bundle options) throws IntentSender.SendIntentException {
mBase.startIntentSender(intent, fillInIntent, flagsMask,
flagsValues, extraFlags, options);
}

@Override
public void sendBroadcast(Intent intent) {
mBase.sendBroadcast(intent);
}

@Override
public void sendBroadcast(Intent intent, String receiverPermission) {
mBase.sendBroadcast(intent, receiverPermission);
}

@Override
public void sendOrderedBroadcast(Intent intent,
String receiverPermission) {
mBase.sendOrderedBroadcast(intent, receiverPermission);
}

@Override
public void sendOrderedBroadcast(
Intent intent, String receiverPermission, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData,
Bundle initialExtras) {
mBase.sendOrderedBroadcast(intent, receiverPermission,
resultReceiver, scheduler, initialCode,
initialData, initialExtras);
}

@Override
public void sendBroadcastAsUser(Intent intent, UserHandle user) {
mBase.sendBroadcastAsUser(intent, user);
}

@Override
public void sendBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission) {
mBase.sendBroadcastAsUser(intent, user, receiverPermission);
}

@Override
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
int initialCode, String initialData, Bundle initialExtras) {
mBase.sendOrderedBroadcastAsUser(intent, user, receiverPermission, resultReceiver,
scheduler, initialCode, initialData, initialExtras);
}

@Override
public void sendStickyBroadcast(Intent intent) {
mBase.sendStickyBroadcast(intent);
}

@Override
public void sendStickyOrderedBroadcast(
Intent intent, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData,
Bundle initialExtras) {
mBase.sendStickyOrderedBroadcast(intent,
resultReceiver, scheduler, initialCode,
initialData, initialExtras);
}

@Override
public void removeStickyBroadcast(Intent intent) {
mBase.removeStickyBroadcast(intent);
}

@Override
public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
mBase.sendStickyBroadcastAsUser(intent, user);
}

@Override
public void sendStickyOrderedBroadcastAsUser(Intent intent,
UserHandle user, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData,
Bundle initialExtras) {
mBase.sendStickyOrderedBroadcastAsUser(intent, user, resultReceiver,
scheduler, initialCode, initialData, initialExtras);
}

@Override
public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
mBase.removeStickyBroadcastAsUser(intent, user);
}

@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}

@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return mBase.registerReceiver(receiver, filter, broadcastPermission,
scheduler);
}

/** @hide */
@Override
public Intent registerReceiverAsUser(
BroadcastReceiver receiver, UserHandle user, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return mBase.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
scheduler);
}

@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
mBase.unregisterReceiver(receiver);
}

@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}

@Override
public boolean stopService(Intent name) {
return mBase.stopService(name);
}

/** @hide */
@Override
public ComponentName startServiceAsUser(Intent service, UserHandle user) {
return mBase.startServiceAsUser(service, user);
}

/** @hide */
@Override
public boolean stopServiceAsUser(Intent name, UserHandle user) {
return mBase.stopServiceAsUser(name, user);
}

@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}

/** @hide */
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags, int userHandle) {
return mBase.bindService(service, conn, flags, userHandle);
}

@Override
public void unbindService(ServiceConnection conn) {
mBase.unbindService(conn);
}

@Override
public boolean startInstrumentation(ComponentName className,
String profileFile, Bundle arguments) {
return mBase.startInstrumentation(className, profileFile, arguments);
}

@Override
public Object getSystemService(String name) {
return mBase.getSystemService(name);
}

@Override
public int checkPermission(String permission, int pid, int uid) {
return mBase.checkPermission(permission, pid, uid);
}

@Override
public int checkCallingPermission(String permission) {
return mBase.checkCallingPermission(permission);
}

@Override
public int checkCallingOrSelfPermission(String permission) {
return mBase.checkCallingOrSelfPermission(permission);
}

@Override
public void enforcePermission(
String permission, int pid, int uid, String message) {
mBase.enforcePermission(permission, pid, uid, message);
}

@Override
public void enforceCallingPermission(String permission, String message) {
mBase.enforceCallingPermission(permission, message);
}

@Override
public void enforceCallingOrSelfPermission(
String permission, String message) {
mBase.enforceCallingOrSelfPermission(permission, message);
}

@Override
public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
mBase.grantUriPermission(toPackage, uri, modeFlags);
}

@Override
public void revokeUriPermission(Uri uri, int modeFlags) {
mBase.revokeUriPermission(uri, modeFlags);
}

@Override
public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
return mBase.checkUriPermission(uri, pid, uid, modeFlags);
}

@Override
public int checkCallingUriPermission(Uri uri, int modeFlags) {
return mBase.checkCallingUriPermission(uri, modeFlags);
}

@Override
public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
return mBase.checkCallingOrSelfUriPermission(uri, modeFlags);
}

@Override
public int checkUriPermission(Uri uri, String readPermission,
String writePermission, int pid, int uid, int modeFlags) {
return mBase.checkUriPermission(uri, readPermission, writePermission,
pid, uid, modeFlags);
}

@Override
public void enforceUriPermission(
Uri uri, int pid, int uid, int modeFlags, String message) {
mBase.enforceUriPermission(uri, pid, uid, modeFlags, message);
}

@Override
public void enforceCallingUriPermission(
Uri uri, int modeFlags, String message) {
mBase.enforceCallingUriPermission(uri, modeFlags, message);
}

@Override
public void enforceCallingOrSelfUriPermission(
Uri uri, int modeFlags, String message) {
mBase.enforceCallingOrSelfUriPermission(uri, modeFlags, message);
}

@Override
public void enforceUriPermission(
Uri uri, String readPermission, String writePermission,
int pid, int uid, int modeFlags, String message) {
mBase.enforceUriPermission(
uri, readPermission, writePermission, pid, uid, modeFlags,
message);
}

@Override
public Context createPackageContext(String packageName, int flags)
throws PackageManager.NameNotFoundException {
return mBase.createPackageContext(packageName, flags);
}

/** @hide */
@Override
public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
throws PackageManager.NameNotFoundException {
return mBase.createPackageContextAsUser(packageName, flags, user);
}

@Override
public Context createConfigurationContext(Configuration overrideConfiguration) {
return mBase.createConfigurationContext(overrideConfiguration);
}

@Override
public Context createDisplayContext(Display display) {
return mBase.createDisplayContext(display);
}

@Override
public boolean isRestricted() {
return mBase.isRestricted();
}

/** @hide */
@Override
public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
return mBase.getCompatibilityInfo(displayId);
}
}

android.view.ContextThemeWrapper:

/**
* A ContextWrapper that allows you to modify the theme from what is in the
* wrapped context.
*/
public class ContextThemeWrapper extends ContextWrapper {
private Context mBase;
private int mThemeResource;
private Resources.Theme mTheme;
private LayoutInflater mInflater;
private Configuration mOverrideConfiguration;
private Resources mResources;

public ContextThemeWrapper() {
super(null);
}

public ContextThemeWrapper(Context base, int themeres) {
super(base);
mBase = base;
mThemeResource = themeres;
}

@Override protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
mBase = newBase;
}

/**
* Call to set an "override configuration" on this context -- this is
* a configuration that replies one or more values of the standard
* configuration that is applied to the context. See
* {@link Context#createConfigurationContext(Configuration)} for more
* information.
*
* <p>This method can only be called once, and must be called before any
* calls to {@link #getResources()} are made.
*/
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
if (mResources != null) {
throw new IllegalStateException("getResources() has already been called");
}
if (mOverrideConfiguration != null) {
throw new IllegalStateException("Override configuration has already been set");
}
mOverrideConfiguration = new Configuration(overrideConfiguration);
}

@Override
public Resources getResources() {
if (mResources != null) {
return mResources;
}
if (mOverrideConfiguration == null) {
mResources = super.getResources();
return mResources;
} else {
Context resc = createConfigurationContext(mOverrideConfiguration);
mResources = resc.getResources();
return mResources;
}
}

@Override public void setTheme(int resid) {
mThemeResource = resid;
initializeTheme();
}

/** @hide */
@Override
public int getThemeResId() {
return mThemeResource;
}

@Override public Resources.Theme getTheme() {
if (mTheme != null) {
return mTheme;
}

mThemeResource = Resources.selectDefaultTheme(mThemeResource,
getApplicationInfo().targetSdkVersion);
initializeTheme();

return mTheme;
}

@Override public Object getSystemService(String name) {
if (LAYOUT_INFLATER_SERVICE.equals(name)) {
if (mInflater == null) {
mInflater = LayoutInflater.from(mBase).cloneInContext(this);
}
return mInflater;
}
return mBase.getSystemService(name);
}

/**
* Called by {@link #setTheme} and {@link #getTheme} to apply a theme
* resource to the current Theme object. Can override to change the
* default (simple) behavior. This method will not be called in multiple
* threads simultaneously.
*
* @param theme The Theme object being modified.
* @param resid The theme style resource being applied to <var>theme</var>.
* @param first Set to true if this is the first time a style is being
* applied to <var>theme</var>.
*/
protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
theme.applyStyle(resid, true);
}

private void initializeTheme() {
final boolean first = mTheme == null;
if (first) {
mTheme = getResources().newTheme();
Resources.Theme theme = mBase.getTheme();
if (theme != null) {
mTheme.setTo(theme);
}
}
onApplyThemeResource(mTheme, mThemeResource, first);
}
}

最佳答案

Why need two copy of "mBase" field in the instance of the derived class here?

不需要两个,因为 super.mBase 从未在 ContextThemeWrapper 中使用过。所以我认为这些字段具有相同的名称只是巧合。

In which case should I override a field defined in base class as private?

您不能覆盖字段。子类中的字段与父类(super class)中的字段不同,即使它们具有相同的名称。我认为 ContextThemeWrapper 中的 mBase 是私有(private)的,因为它不应该从类外部更改(因此没有 getter 和 setter)。


编辑:

But mBase in the two class refer to the same instance of Context. If ContextThemeWrapper doesn't want the client to change the mBase field, just inherit it from ConextWrapper is enough. Why does ContextThemeWrapper contain another reference of the Context instance in ContextWrapper ?

是的,我之前没有看到这个。这很有趣,但让我们看看文档:

"ContextThemeWrapper is a ContextWrapper that allows you to modify the theme from what is in the wrapped context."

"ContextWrapper is a proxying implementation of Context that simply delegates all of its calls to another Context.

所以ContextWrapperService类扩展,ContextThemeWrapperActivity类扩展(还有一些……)。

ContextThemeWrapper 可以修改 Context... 所以当创建这个类的对象时,它用它自己的 mBase(在构造函数中传递)替换父类(super class)中的 mBase。所以两个 mBase 具有相同的值。这样做是因为 ContextThemeWrapper 可以修改传递给它的 Context。当 Context 在 ContextThemeWrapper 中修改时,它也会在 ContextWrapper 中更新,因此 ContextWrapper 及其所有子类都可以访问这个修改后的 Context.

抱歉解释困惑,但我现在没有太多时间,我希望你现在能理解:)

关于java - 为什么 ContextThemeWrapper 会覆盖 ContextWrapper 中定义的字段 "mBase"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15003411/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com