java怎么判断一个frame是否存在 has leaked window android.widget.framelayout怎么解决?

[更新]
·
·
分类:互联网
1839 阅读

has

has leaked window 怎么解决?

leaked window android.widget.framelayout怎么解决?

我想大多数人,对于这3个东西的概念能区分,但是具体区别在哪却很难说出来。 我这里根据我个人的理解来讲讲我个人对这3个概念的理解。当然这里设计到通用的事件窗口模型等通用GUI设计,我这里就不打算讲了,纯粹从概念上来进行区分。 Activity是Android应用程序的载体,允许用户在其上创建一个用户界面,并提供用户处理事件的API,如onKeyEvent, onTouchEvent等。 并维护应用程序的生命周期(由于android应用程序的运行环境和其他操作系统不同,android的应用程序是运行在框架之内,所以他的应用程序不能当当从进程的级别去考虑,而更多是从概念上去考虑。android应用程序是由多个活动堆积而成,而各个活动又有其独立的生命周期)。Activity本身是个庞大的载体,可以理解成是应用程序的载体,如果木有Activity,android应用将无法运行。也可以理解成android应用程序的入口。Acivity的实例对象由系统维护。系统服务ActivityManager负责维护Activity的实例对象,并根据运行状态维护其状态信息。 但在用户级别,程序员可能根愿意理解成为一个界面的载体。但仅仅是个载体,它本身并不负责任何绘制。Activity的内部实现,实际上是聚了一个Window对象。Window是一个抽象类,它的具体是在android_src_home/framework/policies/base/phone/com/android/internal/policy/impl目录下的。 当我们调用Acitivity的 setContentView方法的时候实际上是调用的Window对象的setContentView方法,所以我们可以看出Activity中关于界面的绘制实际上全是交给Window对象来做的。绘制类图的话,可以看出Activity聚合了一个Window对象。 下面是PhoneWindow中的setContentView方法的实现: @Override public void setContentView(View view, params) { if (mContentParent null) { installDecor() } else { () } (view, params) final Callback cb getCallback() if (cb ! null) { cb.onContentChanged() } } Window内部首先判断mContentParent是否为空,然后调用installDecor方法(安装装饰器),我们看看这个方法如何实现的 private void installDecor() { if (mDecor null) { mDecor generateDecor() (true) } if (mContentParent null) { mContentParent generateLayout(mDecor) mTitleView (TextView)findViewById() if (mTitleView ! null) { if ((getLocalFeatures() amp (1 ltlt FEATURE_NO_TITLE)) ! 0) { View titleContainer findViewById(_container) if (titleContainer ! null) { (View.GONE) } else { (View.GONE) } if (mContentParent instanceof FrameLayout) { ((FrameLayout)mContentParent).setForeground(null) } } else { (mTitle) } } } } 在该方法中,首先创建一个DecorView,DecorView是一个扩张FrameLayout的类,是所有窗口的根View。我们在Activity中调用的setConctentView就是放到DecorView中了。这是我们类图的聚合关系如下: Activity---gtWindow---gtDecorView 这是我们得出这3个类之间最直接的一个关系。 我们详细分析一下,类对象是如何被创建的。 先不考虑Activity的创建(因为 Acitivity的实例由ActivityManager维护,是在另一个进程设计到IPC的通信,后面会讲到),而考虑Window和View的创建。 Activity被创建后,系统会调用它的attach方法来将Activity添加到ActivityThread当中。我们找到Activity的attach方法如下: 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, Object lastNonConfigurationInstance, HashMapltString,Objectgt lastNonConfigurationChildInstances, Configuration config) { attachBaseContext(context) mWindow (this) (this) if ( ! _INPUT_STATE_UNSPECIFIED) { () } mUiThread () mMainThread aThread mInstrumentation instr mToken token mIdent ident mApplication application mIntent intent mComponent () mActivityInfo info mTitle title mParent parent mEmbeddedID id mLastNonConfigurationInstance lastNonConfigurationInstance mLastNonConfigurationChildInstances lastNonConfigurationChildInstances (null, mToken, mComponent.flattenToString()) if (mParent ! null) { (()) } mWindowManager () mCurrentConfig config } 我们看红色的代码部分,就是创建Window对象的代码。感兴趣的同学可以跟踪去看看具体是如何创建的。其实很简单,其内部实现调用了Policy对象的makeNewWindow方法,其方法直接new了一个PhoneWindow对象如下: public PhoneWindow makeNewWindow(Context context) { return new PhoneWindow(context) } 这时我们已经可以把流程串起来,Activity创建后系统会调用其attach方法,将其添加到ActivityThread当中,在attach方法中创建了一个window对象。 下面分析View的创建。我们知道Window聚合了DocerView,当用户调用setContentView的时候会把一颗View树仍给树是已经创建好的实例对象了,所以我们研究的是DocerView是个什么东西,它是如何被创建的。 我们回头看看Window实现里边的setContentView方法,我们看上面代码的红色部分setContentView-gt installDecor-gt generateDecor. generateDecor直接new了一个DecorView对象: protected DecorView generateDecor() { return new DecorView(getContext(), -1) } 我们可以去看看DecorView的实现,它是PhoneWindow的一个内部类。实现很简单,它默认会包含一个灰色的标题栏,然后在标题栏下边会包含一个空白区域用来当用户调用setContentView的时候放置用户View,并传递事件,这里不做详细分析,感兴趣同学可以自己研究研究。 当DecorView创建好之后再回到Window中的setContentView方法中来,见上面代码蓝色部分,调用 (view, params) 来将用户的View树添加到DecorView中。 到这时为止,我想我们已经很清晰的认识到它们3者之间的关系,并知道其创建流程。 现在总结一下: Activity在onCreate之前调用attach方法,在attach方法中会创建window对象。window对象创建时并木有创建Decor对象对象。用户在Activity中调用setContentView,然后调用window的setContentView,这时会检查DecorView是否存在,如果不存在则创建DecorView对象,然后把用户自己的View 添加到DecorView中。

JAVA中错误:类X是公共的,应在名为的文件中声明public class X extends JFrame { 为什么会这样?

你是将这三个类存在一个文件里了吧这三个类MyFrame,Number,MyFrameDemo都被声明为public了,但一个文件只能有一个包含public类.所以,你要么将三个类存于三个文件,分别编译;要么将非主类去掉public修饰