我正在创建一个主/详细类型的应用程序。主视图是一个显示主项目列表的MasterFragment,而详细信息视图是一个显示详细项目列表的DetailsFragment。
当用户点击列表中的主项目时,我创建一个新的DetailsFragment并使用事务显示它。
DetailFragment中显示的详细信息需要一些时间来加载(秒),所以我想在后台线程中加载它们并在加载完成后显示列表。
我现在想让用户选择长按主项目,而不是立即打开并让他等待,将在后台创建DetailsFragment(尚未显示),允许他浏览MasterFragment正在加载。导航项目将添加到导航抽屉中,以便在完成加载后的一段时间内导航到DetailsFragment。
想想就像在非常慢的互联网上使用网络浏览器 - 而不是打开一个页面并等待它加载它在后台的新标签页中打开页面更好,同时浏览当前页面更多它会加载,然后在您认为必须完成加载时返回到新选项卡。除了碎片之外,这也是我想在我的应用中做的事情。
现在我了解到,通过创建Fragments,使用创建Fragment的静态工厂方法很重要,将任何对象作为参数添加到Bundle中,然后只留下一个空构造函数。
public class DetailsFragment : Fragment
{
public DetailsFragment()
{
// Leave empty
}
public static DetailsFragment create(int masterId)
{
DetailsFragment f = new DetailsFragment();
Bundle args = new Bundle();
bundle.putInt("MasterId", masterId);
f.setArguments(args);
return f;
}
@Override
private void onCreate(Bundle bundle)
{
super.onCreate(bundle);
// Get master ID
int masterId = getArguments().getInt("MasterId");
// Load details in background thread
load(masterId);
}
@Background
private void load(int masterId)
{
//... (loading takes a few seconds...)
loadFinished();
}
@UiThread
private void loadFinished()
{
// update view...
}
}
(注意:我正在使用Android Annotations,以便在后台运行' load'方法(带有@Background注释)。只是假装我使用跑步者或AsyncTask等开始它。)
然而,这里存在一个问题:在调用片段之前不会调用onCreate,换句话说,在用户打开细节片段之前不会进行加载。我试过onAttach而不是onCreate,但同样的事情发生了。似乎onAttach是生命周期中调用的第一个方法,已经太晚了。
我希望加载立即开始,即使片段尚未显示(如果用户不再导航到它,则可能永远不会显示)。
如何实现此行为?
答案 0 :(得分:0)
这是我预加载片段的方式。不确定它是最好的方式还是android方式,但这是我想出怎么做的方式。
在我的布局xml中,我有以下内容:
<FrameLayout
android:id="@+id/master_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible" />
<FrameLayout
android:id="@+id/details_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"/>
请注意,“details_frame”是不可见的。然后,当您想要预加载片段时,将片段替换为不可见的details_frame,它将保持不可见:
getSupportFragmentManager().beginTransaction()
.replace(R.id.details_frame, <DetailsFragment>, <FragmentName>)
.commit();
然后,一旦您想要显示它,您就可以将可见性更改为可见而不是不可见。
findViewById(R.id.details_frame).setVisibilility(View.VISIBLE);