Android 不同步的,不规则的
Android在其支持libaray版本24.0及更高版本中添加了一个新的Android 不同步的,不规则的,android,multithreading,performance,android-layout,android-fragments,Android,Multithreading,Performance,Android Layout,Android Fragments,Android在其支持libaray版本24.0及更高版本中添加了一个新的AsyncLayoutFlater类,可用于Android SDK 4.0或更高版本(几乎所有可用设备)。 根据Android的文档 用于异步扩展布局的帮助器类。使用、建造 UI线程和调用上的AsyncLayoutFlater实例 充气(int、ViewGroup、OnInflateFinishedListener)。这个 将在上调用AsyncLayoutFlater.OnInflateFinishedListener 充
AsyncLayoutFlater
类,可用于Android SDK 4.0或更高版本(几乎所有可用设备)。根据Android的文档 用于异步扩展布局的帮助器类。使用、建造 UI线程和调用上的AsyncLayoutFlater实例 充气(int、ViewGroup、OnInflateFinishedListener)。这个 将在上调用AsyncLayoutFlater.OnInflateFinishedListener 充气请求完成时的UI线程 这是为了 延迟创建或响应用户请求的UI部分 互动。这允许UI线程继续响应& 在执行相对较重的充气时设置动画 事实上,我发现这很有用,正如您可能意识到的,或者您可能没有意识到的那样,在时间上膨胀复杂视图是一项昂贵的操作,有时需要100毫秒。因此,当它在主线程上膨胀时,UI可能会变得迟钝。
我发现的另一个好处是,活动的加载时间更快,因为UI线程可以继续加载的下一步,而视图会单独膨胀。我有时能够使用此方法显著加快应用程序启动时间。
也就是说,当使用单独的线程膨胀视图时,可能会出现陷阱。我们将在回答中解释它们。根据Android文档 对于要异步膨胀的布局,它需要有一个父级 其generateLayoutParams(AttributeSet)是线程安全的,并且所有 作为通货膨胀一部分构建的视图不得创建任何 处理程序或以其他方式调用myLooper()。如果正在尝试的布局 无论出于何种原因,都不能异步构造, 充气机将自动退回到充气状态 用户界面线程 这是你必须注意的事情。虽然您的应用程序不会崩溃,因为AsyncLayoutFlater将自动退回到UI线程上的膨胀,但现在膨胀所需的时间将增加一倍,首先在单独的线程上,然后在UI线程上。因此,仔细观察日志,看看AsyncLayoutFlater是否抱怨它在UI线程上膨胀,并处理它。
您可能需要在多个设备和操作系统版本上进行测试,因为同一视图可能(未确认)在某些设备中创建处理程序,而在其他设备中不创建处理程序。好消息是,您不必做到完美,因为在最坏的情况下,它仍然不会崩溃,因为AsyncLayoutFlater会处理它。
通常,问题是创建处理程序的单个自定义视图。对此,一个非常简单的解决方法是将该视图替换为
ViewStub
,然后在调用OnInflateFinishedListener
回调时将其膨胀。
例如:
<ViewStub android:id="@+id/stub"
android:inflatedId="@+id/subTree"
android:layout="@layout/mySubTree"
android:layout_width="120dip"
android:layout_height="40dip" />
还有一个危险的可怜虫,它花费了我很多小时的调试。它与Android活动和片段生命周期有关。正如我们所知,Android可以随时在不在前台的情况下杀死某个活动。当这种情况发生时,Android将在需要显示时重新创建活动。它使用
savedInstance
捆绑包将活动和片段恢复到以前的状态。但是活动和片段之间有很大的区别。对于活动,操作系统不会重新创建视图,应用程序必须重新创建视图。重新创建视图后,操作系统将通过调用
onRestoreState
恢复每个视图的状态 但通过片段,操作系统实际上会重新创建整个片段视图,应用程序只需初始化类成员。
这在使用AsyncLayoutFlater时会导致一个严重的问题,因为当第一次创建活动时,虽然
onCreate
函数在视图膨胀之前完成(因为它在单独的线程上膨胀),但我们仍然不会创建和附加任何片段,直到调用OnInflateFinishedListener
回调。因此,当片段被创建时,我们已经有了一个完整的工作活动和一个工作视图。但是当操作系统重新创建活动时,一旦Activity
onCreate
函数完成,也就是视图膨胀之前(在单独的线程中膨胀),操作系统就会认为是时候重新创建片段了。然后,它将调用onCreateView
,甚至调用onActivityCreated
,即使活动的视图尚未膨胀和设置。这将导致许多崩溃和不可见的碎片解决方法是检查活动的
onCreate
函数(如果正在重新创建),方法是检查传递的savedBundle
是否为null
,并且在这种情况下不使用AsyncLayoutFlater。为此,将AsyncLayoutFlater.OnInflateFinishedListener
实例分配给一个变量,并在膨胀视图后直接调用它。这将导致代码稍微复杂一些,但不会太复杂。它看起来像这样
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
final AsyncLayoutInflater.OnInflateFinishedListener callback = new AsyncLayoutInflater.OnInflateFinishedListener()
{
@Override
public void onInflateFinished(View view, int resid, ViewGroup parent)
{
// setup here
}
};
if (savedInstanceState == null) {
AsyncLayoutInflater inflater = new AsyncLayoutInflater(this);
inflater.inflate(R.layout.main, null, callback);
} else {
View view = getLayoutInflater().inflate(R.layout.main, null);
Callback.onInflateFinished(view, R.layout.main, null)
}
}
好了,现在就这样。如果您有任何建议或意见,请随时在下面发表评论。
祝你好运
狮子座
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
final AsyncLayoutInflater.OnInflateFinishedListener callback = new AsyncLayoutInflater.OnInflateFinishedListener()
{
@Override
public void onInflateFinished(View view, int resid, ViewGroup parent)
{
// setup here
}
};
if (savedInstanceState == null) {
AsyncLayoutInflater inflater = new AsyncLayoutInflater(this);
inflater.inflate(R.layout.main, null, callback);
} else {
View view = getLayoutInflater().inflate(R.layout.main, null);
Callback.onInflateFinished(view, R.layout.main, null)
}
}