1fragment嵌套fragment时出现getActivity()为null
activity A嵌套fragment B,B嵌套fragment C,C跳转到activity D,当activity D被finish掉之后,C中容易爆出getActivity为空如果你的activity被回收了,那你需要在bundle中保存一下fragment信息,我的解决方法:fragment实例化之后会到activity的fragmentManager中注册一下,这个动作封装在fragment中的onAttach(Activity activity)方法中,可以直接在onAttach(Activity activity)方法中去赋值
2fragment嵌套fragment时没有执行子fragment的onActivityResult方法
activity A嵌套fragment B,B嵌套fragment C,C通过startActivityForResult跳转到activity D,当activity D被finish掉之后,没有执行C的onActivityResult
其实这个问题也不是每个人都会遇到,当activity A和Fragment B不重写onActivityResult方法,可能就不会出现这个问题,但是我的activity A重写了onActivityResult方法,所以当activity D被销毁的时候,直接去执行activity 的onActivityResult,其实这个问题也很简单,只是遇到的时候可能想不到,解决方案就是在Activity中的onActivityResult方法中加入superonActivityResult(requestCode, resultCode, data);一切都ok了
Activity的onActivityResult方法:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
superonActivityResult(requestCode, resultCode, data);
fragment的onActivityResult方法:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
ViewPager中如何获取Fragment
在做项目时,遇到Fragment与Fragment、Fragment与Activity需要相互通信、传递数据以及进行互
*** 作的问题,查阅了官方文档,也实现了官方的例子,但实际项目是ViewPager+Fragment,按官方的例
子,总是获取不到Fragment的引用,如:
HeadLinesFragment headLinesFrag = (HeadLinesFragment)
getSupportFragmentManager()findFragmentById(Ridheadline_fragment);
这是因为在ViewPager里Fragment是new出来动态加到ViewPager里的,上需的Id只是Fragment的布
局文件的根Id,不是Fragment 的Id,故获取的Fragment为空
查询相关资料后,终于找到如下解决方案:
一般来讲,我们再使用viewpager的时候,是在代码中动态的添加fragment。此时,我们不能去指定
fragment的id,也不能指定他的tag,如果你一定要去指定tag,运行时会提示,tag已经被指定。那么,在动
态的添加了fragment之后,我们如何能获取到该fragment并修改其中的内容呢。两种方法:
第一种方法实际上是一种hack方法,并没有官方文档说明支持。代码如下:
SomeFragment someFragment = getSupportFragmentManager()FindFragmentByTag(“android:switcher:” + Ridviewpager + “:0″);
if (someFragment != null) //可能没有实例化
{
if (someFragmentgetView() != null)
{
someFragmentupdateView();//自定义方法更新
}
}
这里要记住的就是”android:switcher:” + Ridviewpager + “:0″ 这个字符窜表示的就是该
fragment的tag,其中0 是fragment 在viewpager中的位置。
第二种方法更正规,因为第一种方法对基于FragmentPagerAdapter的实现是有效的,但对于
FragmentStatePagerAdapter就无效了。因为FragmentStatePagerAdapter不会对传给
FragmentManager的Fragment设置tag
ViewPager pager = (ViewPager)findViewById(Ridviewpager);
FragmentStatePagerAdapter f = pagergetAdapter();
SomeFragment someFragment = (SomeFragment)finstantiateItem(pager,position);
instantiateItem(pager,position)方法会返回在position位置的fragment的引用。如果该
fragment 已经实例化了,再次调用instantiateItem(pager,position)的时候,该方法并不会调用
getItem()来再次实例化fragment,而是直接返回引用。
方法三更简单:
Activity里的语句:
mPagerAdapter = new DownloadSlidePagerAdapter(getSupportFragmentManager());
LocalVideoListFragment fragment = ((LocalVideoListFragment)mPagerAdaptergetItem(mCurrItem));
fragmentrefresh();
DownloadSlidePagerAdapter:
public class DownloadSlidePagerAdapter extends FragmentPagerAdapter {
Fragment[] fragments = {new DownloadListFragment(),new LocalVideoListFragment()};
public DownloadSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return fragments[position];
}
@Override
public int getCount() {
return fragmentslength;
}
}
直接获取new的实例对象应用
frgment被创建的时候,相关的生命周期,
onAttach(), onCreate(), onCreateView(), onActivityCreated();
fragment对用户可见的时候,相关的生命周期,
onStrat(), onResume(),
fragment进入“后台模式”的时候,相关的生命周期,
onPause(), onStop(),
fragment被销毁的时候,相关的生命周期,
onPause(), onStop(), onDestroyView(), onDestroy(), onDetach()
可用onCreate()、onCreateView()、onActivityCreated()方法Bundle对象保存一个fragment的对象
onAttach():Fragment和Activity相关联时调用,可以通过该方法获取Activity引用,还可以通过getArguments()获取参数。
onCreate():Fragment创建时被调用。
onCreateView():创建Fragment的布局。
onActivityCreated():当Activity完成onCreate时调用。
onStart():当Fragment可见时。
onResume():当Fragment可见,且可交互时调用。
onPause():当Fragment不可交互,但可见时。
onStop():当Fragment不可见时。
onDestroyView():当Fragment的UI从视图结构中移除时调用。
onDestroy():销毁Fragment时
onDetach():当Fragment和Activity解除关联时调用。
public void intialiseViewPager()
{
List<Fragment> fragments = new Vector<Fragment>();
numberOfTabs = applicationcurrentReportgetODTabsList()size();
for (int i = 0; i < numberOfTabs; i++)
{
ODTab tempTab = applicationcurrentReportgetODTabsList()get(i);
if (tempTabgetTabType()equals(ODGridXML_GRID_ELEMENT))
{
GridFragment gridFragment = GridFragmentnewInstance(tempTabgetTabId());
fragmentsadd(gridFragment);
}
else if (tempTabgetTabType()equals(ODChartXML_CHART_ELEMENT))
{
NewChartFragment chartFragment = NewChartFragmentnewInstance(tempTabgetTabId());
fragmentsadd(chartFragment);
}
}
Logd(TAG, "Current report fragments set to adapter: "+fragmentstoString());
mPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), fragments);
mViewPager = (ViewPager)findViewById(Ridpager);
mViewPagersetAdapter(mPagerAdapter);
mViewPagersetOffscreenPageLimit(0);
mViewPagersetOnPageChangeListener(this);
}
你可以看到我将字符串传递到片段 ( tempTabgetTabId() ),在这一行:
GridFragment gridFragment = GridFragmentnewInstance(tempTabgetTabId());
当片段中它自已我这样做对其进行初始化:
public static final GridFragment newInstance(String tabId)
{
GridFragment f = new GridFragment();
Bundle bdl = new Bundle(2);
bdlputString(TAB_ID, tabId);
fsetArguments(bdl);
return f;
}
@Override
public void onCreate(Bundle savedInstanceState)
{
String tabId = getArguments()getString(TAB_ID);
if (applicationcurrentReport != null)
{
thisodTab = applicationcurrentReportgetODTabByTabId(tabId);
}
else
{
startActivity(new Intent(getActivity(), LoginScrActivityclass));
}
superonCreate(savedInstanceState);
}
所有这一切被执行,不会覆盖默认空的构造函数的片段,按照我的理解这非常不建议。
现在我需要获取实例的 odTab 对象放进这行中的当前可见片段:
thisodTab = applicationcurrentReportgetODTabByTabId(tabId);
可能有些人请给我解释如何做到这吗?所以我可以把它的 odTab 对象,如何获取当前可见片段实例
更新:这里提出的意见与我加入了 odTab 到调用的应用程序类的对象实例 currentVisibleTab 和我设置 odTab 这样的实例:
@Override
public void setUserVisibleHint(boolean isVisibleToUser)
{
Logd(TAG, "setUserVisibleHint invoked!");
supersetUserVisibleHint(isVisibleToUser);
if (isVisibleToUser)
{
if (odTab != null && getActivity() != null)
{
Logd(TAG, "Currently visable tab: "+odTabgetTabTitle());
applicationcurrentVisibleTab = odTab;
}
}
}
更新 2:我有一种 ViewPagerAdapter :
public class ViewPagerAdapter extends FragmentPagerAdapter
{
private List<Fragment> fragments;
/
@param fm
@param fragments
/
public ViewPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
thisfragments = fragments;
}
/ (non-Javadoc)
@see androidsupportv4appFragmentPagerAdapter#getItem(int)
/
@Override
public Fragment getItem(int position) {
return thisfragmentsget(position);
}
/ (non-Javadoc)
@see androidsupportv4viewPagerAdapter#getCount()
/
@Override
public int getCount() {
return thisfragmentssize();
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
public void removeAllFragments()
{
thisfragmentsclear();
}
public void addFragmentsListToAdapter(List<Fragment> fragments)
{
thisfragmentsaddAll(fragments);
}
public List<Fragment> getFragments()
{
return fragments;
}
}
在它正如你看到的我有 List 的片段所示的 ViewPager ,此列表初始化像这样:
List<Fragment> fragments = new Vector<Fragment>();
我不明白的是如何获取对当前段落触发从该列表中的接口方法的引用。不相关的问题,但也许你知道答案,有什么区别之间List 和 Vector
我还查阅了此选项。
先谢谢了。
解决方法 1:
我找到的方法 visbile 片段当前正在使用 setUserVisibleHint 和回视图寻呼机的接口。此方法是在类中片段。重写它和使用回叫您查看传呼机的接口。如果该片段是可见-即它返回 true-只使用对您片段 (无论是从列表中备份您的适配器或一个您存储为一个实例变量) 的引用以获取您需要的任何从片段本身。我已经添加下面的代码。
声明有关的无论你想做一个接口。我的情况我用这来禁用 ViewPager 默认 x 方向侦听器时一个谷歌地图实例是可见的因此滚动地图没有触发片段的变化。
public interface OnMapFragmetnVisibleListener{
public void mapVisible(boolean visible);
}
在片段:
@Override
public void onAttach(Activity activity){
superonAttach(activity);
try{
mapFragmentVisibilityListener = (OnMapFragmentVisibleListener) activity;
isAttached = true; //flag for whether this framgnet is attache to pager
} catch (ClassCastException e){
throw new ClassCastException(activitytoString() + " must implement interface onAttach");
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser){
if(isVisibleToUser && isAttached){ //if listner is called before fragment is attached will throw NPE
mapFragmentVisibilityListenermapVisible(true);
}
}
直到我试过这个是不明显的一件事是 isAttached 变量的加法。我也重写片段 onAttach 方法,并将其设置为 true,一旦它被称为。否则会发生什么是您片段将对用户是可见的和尝试调用的接口向您 ViewPager 接口初始化之前。
在我 ViewPager 我只是实现了 OnMapFragmentVisibleListener,然后添加所需的方法
@Override
public void mapVisible(boolean visible) {
if(visible)
viewPagerallowSwipe(false); //turn off viewPager intercept touch if map visible
}
在我的案子我用它来关闭 ViewPager 刷功能但是,我可以轻松地叫回来的公共方法中我 mapFragment。我碰巧有 3 片段我 ViewPager 我保持对的引用
更新
要查找当前的片段首先显示你需要找出哪个片段正在显示你可以通过多种方式。最简单的方法就是通过一些描述符返回到您ViewPager / FragmentActivity 与您之前创建的接口。
public interface OnFragmentVisibleListener{
public void fragmentVisible(boolean true, String tag);
}
那您设置的问题是您正在使用 Vector ,是真的同步 List 来存储您片段 rerefences。其结果是,没有通过,你可以找到你片段以后的密钥值。片段有确定的一个标签,创建在片段获利的能力,它们被添加到该片段活动期间。然而,在 ViewPager设置,您没有添加片段分别,所以无法添加标签在获利。
我的解决方案一直是回我 BasePagerAdapter 与 HashMap 在其中存储由一个唯一的密钥标识每个片段。
LinkedHashMap<String, Fragment> tabs = new LinkedHashMap<String, Fragment>();
tabsput("Frag1", fragment1);
tabsput("Frag2", fragment2);
tabsput("Frag3", fragment3);
然后用此适配器
private class BasePagerAdapter extends FragmentPagerAdapter{
private LinkedHashMap<String, Fragment> tabs;
public BasePagerAdapter(LinkedHashMap<String, Fragment> tabMap, FragmentManager fm)
{
super(fm);
thistabs = tabMap;
}
// other basic methods
因为您的引用存储到一个密钥值、 容易找到因为你只是可以通过从键值哈希映射和返回键搜索你要找的 framgment。
如果您不能更改设置要逃离 Vector 你需要到任一 (1) 跟踪的哪个片段你添加的顺序 (假设片段不添加和删除动态) 这样,你可以通过对每个片段 (2) 保持单独引用或索引
private Fragment x;
//in onCreate
x = new Fragment();
//in interface
if(tagequals("x"){
xdoSomething();
}
我们通常是用
getSupportFragmentManager()beginTransaction()replace(Ridfragment_view, fragment)commit();
来添加fragment到指定的视图位置。所以你的需求只需你动态的改变需要替换的这个view的位置就好了,替换流程还是不变的。
动态的改变view的位置,这需要你在java代码里动态的设置view的位置。
一、使用Fragment获取控件Id
我是在MainActivity中通过Fragment的事务管理把各个fragment添加到MainActivity中的,但是MainActivity中并没有很多控件,控件大都在各个fragment的布局里面,所以如何在fragmen中获取控件Id是一件非常重要的事!话不多说直接上代码!
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View messageLayout=inflaterinflate(Rlayoutmessage_layout,container,false); inspect= (TextView) messageLayoutfindViewById(Ridinspect); inspectsetOnClickListener(new ViewOnClickListener() {
在OncreatView方法中,先是通过View方法把布局加载到fragmnet中,然后在使用加载的布局中的findViewById的方法找到控件,这和之前的用法是不一样的,之前是直接findViewById。
二、如何在fragment中跳转Activity
话不多话,直接上代码!
Intent intent=new Intent(getActivity(),InspectActivityclass);startActivity(intent);
与平常跳转不同的地方在于这里是:
new Intent(getActivity(),InspectActivityclass);
使用 MVPArms 开发也有一段时间了,首先感谢 作者 的无私奉献和分享!在此记录一下 Fragment 使用过程中遇到的问题和解决方案。
Activity 和 Fragment 的生命周期如下:
<div align=center>
<div align=center>
</div>
<div align=center>
</div>
MVPArms 框架对 Activity 和 Fragment 的生命周期进行了很好的封装。
通过 ActivityDelegate 代理 Activity 的生命周期(具体实现为 ActivityDelegateImpl ),通过 FragmentDelegate 代理 Fragment 的生命周期(具体实现为 FragmentDelegateImpl );
然后在 ActivityLifecycle 实现了 ApplicationActivityLifecycleCallbacks 接口,内部类 FragmentLifecycle 实现了 FragmentManagerFragmentLifecycleCallbacks 抽象类;
并将 ActivityLifecycle 注入到 BaseApplication 中,注入过程是通过 AppDelegate 来代理 Application 的生命周期完成的。
为此作者还专门通过 一篇文章 介绍思想,收获颇多。
ApplicationActivityLifecycleCallbacks 接口定义如下:
FragmentManagerFragmentLifecycleCallbacks 抽象类定义如下:
MainActivity 有三个 Fragment,分别是 HomeFragment , DashboardFragment , NotificationsFragment 。
MainActivity 控制 Fragment 的切换,其中 HomeFragment 是主页。
使用 ARouter 控制 Fragment 的切换。
设置 MainActivity 的启动模式为 singleTask ,在 AndroidManifestxml 中为 MainActivity 添加以下属性:
MainActivity 的布局文件包含了一个 FramLayout,用来动态添加 Fragment;还包含了一个 BottomNavigationView,在 Activity 中控制 Fragment 的切换。
MainActivity 中有一个 List 用来存储 Fragment,根据每个 Fragment 在 List 中的索引切换 Fragment。此处的切换方式使用的是 hide/show 的方式,当 Fragment 需要频繁切换的时候,这样做比 replace 的方式更有效率。
每个 Fragment 的布局文件都有两个 Button,用来在一个 Fragment 切换至其他的 Fragment。
具体实现方式是由 ARouter 先跳转到 Activity,然后由 Activity 控制 Fragment 的切换。
在 Fragment 通过 ARouter 跳转到 Activity,会触发 Activity 的 onNewIntent(Intent intent) 方法回调,所以在 onNewIntent 处理ARouter 携带的要切换的目标 Fragment 的索引,然后通过 BottomNavigationView 的 OnNavigationItemSelectedListener 控制切换 Fragment,同时设置 Toolbar 的 Title。从而完成从一个 Fragment 切换至其他的 Fragment。
由于同一个 Activity 与三个 Fragment 的生命周期同步,所以当 Activity 在 onResume 状态下,三个 Fragment 也在同时 onResume,使用 hide/show 的方式切换 Fragment 无法刷新 Fragment 的状态。这时候 onHiddenChanged(boolean hidden) 方法就派上用场了,可以在 Fragment 中重写此方法来处理刷新等逻辑。
当设备旋转或者 Activity 长期处于后台而被系统回收,Activity 的会经历销毁->重建的过程。但是我们可以保存 Fragment,当 Activity 重建时继续使用已经存在的 Fragment 实例,避免浪费系统资源。
利用系统 API 提供的 Fragment#setRetainInstance(boolean retain) 方法来保存 Fragment 实例,在 GlobalConfiguration 的 FragmentLifecycleCallbacks 回调方法里设为 true。
因为 FargmentManager 在 Activity 重建时会自动恢复,所以可以在添加 Fragment 时设置 tag,然后通过 FragmentManager#findFragmentByTag(String tag) 获取 FragmentManager 中已存在的 Fragment 实例。
这里使用了 FragmentUtils 工具类处理 Fragment。
在 Activity 的 onSaveInstanceState(Bundle outState) 保存当前 Fragment 索引:
在 Activity 的 initData(Bundle savedInstanceState) 恢复原来 Fragment 索引:
在 Activity 中持有 各个 Fragment 实例,MVPArms 的 IFragment 接口提供一个 setData(Object data) 方法,可以将通信数据传递给目标 Fragment:
然后在 Fragment 中重写 setData() 方法接收消息,根据消息做一些事情:
使用 ARouter 将 通信数据携带发送给 Activity,然后在 Activity 的 onNewIntent(Intent intent) 接收处理。
Fragment 之间的通信可以通过 Fragment 先与 Activity 通信,然后由 Activity 传递给目标 Fragment。例如上面的通过按钮切换 Fragment 就是一个例子。通过 ARouter 来实现。
Activity 也可以在布局文件里直接使用 <fragment> 标签来静态加载 Fragment。
<fragment> 中的 android:name 属性指定要在布局中实例化的 Fragment 类。
当系统创建此 Activity 布局时,会实例化在布局中指定的每个片段,并为每个片段调用 onCreateView() 方法,以检索每个片段的布局。系统会直接插入片段返回的 View 来替代 <fragment> 元素。
用法如下:
欢迎 star 和 issue:
我是 xiaobailong24 ,您可以通过以下平台找到我:
以上就是关于一个fragment中嵌套两个fragment的布局怎么写全部的内容,包括:一个fragment中嵌套两个fragment的布局怎么写、求助,fragment通过findFragmentByTag获取到的是空值、Android的Fragment知识点等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)