Android Fragment 你应该知道的一切

super.onActivityResult(requestCode, resultCode, data);

if(requestCode == REQUEST_DETAIL)

{

mTitles.set(mCurrentPos, mTitles.get(mCurrentPos)+" – "+data.getStringExtra(ContentFragment.RESPONSE));

mAdapter.notifyDataSetChanged();

}

}

}

ContentFragment

public class ContentFragment extends Fragment

{

private String mArgument;

public static final String ARGUMENT = “argument”;

public static final String RESPONSE = “response”;

@Override

public void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

Bundle bundle = getArguments();

if (bundle != null)

{

mArgument = bundle.getString(ARGUMENT);

Intent intent = new Intent();

intent.putExtra(RESPONSE, “good”);

getActivity().setResult(ListTitleFragment.REQUEST_DETAIL, intent);

}

}

public static ContentFragment newInstance(String argument)

{

Bundle bundle = new Bundle();

bundle.putString(ARGUMENT, argument);

ContentFragment contentFragment = new ContentFragment();

contentFragment.setArguments(bundle);

return contentFragment;

}

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState)

{

Random random = new Random();

TextView tv = new TextView(getActivity());

tv.setText(mArgument);

tv.setGravity(Gravity.CENTER);

tv.setBackgroundColor(Color.argb(random.nextInt(100),

random.nextInt(255), random.nextInt(255), random.nextInt(255)));

return tv;

}

}

贴出了两个Fragment的代码,可以看到我们在ListTitleFragment.onListItemClick,使用startActivityForResult()跳转到目标Activity,在目标Activity的Fragment(ContentFragment)中获取参数,然后调用getActivity().setResult(ListTitleFragment.REQUEST_DETAIL, intent);进行设置返回的数据;最后在ListTitleFragment.onActivityResult()拿到返回的数据进行回显;

为大家以后在遇到类似问题时,提供了解决方案;也说明了一个问题:fragment能够从Activity中接收返回结果,但是其自设无法产生返回结果,只有Activity拥有返回结果。

接下来我要贴一下,这两个Fragment的宿主Activity:

ListTitleActivity

public class ListTitleActivity extends FragmentActivity

{

private ListTitleFragment mListFragment;

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_single_fragment);

FragmentManager fm = getSupportFragmentManager();

mListFragment = (ListTitleFragment) fm.findFragmentById(R.id.id_fragment_container);

if(mListFragment == null )

{

mListFragment = new ListTitleFragment();

fm.beginTransaction().add(R.id.id_fragment_container,mListFragment).commit();

}

}

}

ContentActivity:

public class ContentActivity extends FragmentActivity

{

private ContentFragment mContentFragment;

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_single_fragment);

FragmentManager fm = getSupportFragmentManager();

mContentFragment = (ContentFragment) fm.findFragmentById(R.id.id_fragment_container);

if(mContentFragment == null )

{

String title = getIntent().getStringExtra(ContentFragment.ARGUMENT);

mContentFragment = ContentFragment.newInstance(title);

fm.beginTransaction().add(R.id.id_fragment_container,mContentFragment).commit();

}

}

}

有没有发现两个Activity中的代码极其的类似,且使用了同一个布局文件:

activity_single_fragment.xml

<RelativeLayout xmlns:android=“http://schemas.android.com/apk/res/android”

xmlns:tools=“http://schemas.android.com/tools”

android:layout_width=“match_parent”

android:layout_height=“match_parent”

android:id=“@+id/id_fragment_container”

为什么要贴这Acticity的代码呢?因为我们项目中,如果原则上使用Fragment,会发现大量类似的代码,那么我们就可以抽象一个Activity出来,托管我们的Single Fragment。

详细见下一节。

4、SingleFragmentActivity

========================

于是抽象出来的Activity的代码为:

package com.example.demo_zhy_23_fragments;

import android.os.Bundle;

import android.support.v4.app.Fragment;

import android.support.v4.app.FragmentActivity;

import android.support.v4.app.FragmentManager;

public abstract class SingleFragmentActivity extends FragmentActivity

{

protected abstract Fragment createFragment();

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_single_fragment);

FragmentManager fm = getSupportFragmentManager();

Fragment fragment =fm.findFragmentById(R.id.id_fragment_container);

if(fragment == null )

{

fragment = createFragment() ;

fm.beginTransaction().add(R.id.id_fragment_container,fragment).commit();

}

}

}

那么,有了这个SingleFragmentActivity,我们的ContentActivity和ListTitleActivity也能大变身了~

package com.example.demo_zhy_23_fragments;

import android.support.v4.app.Fragment;

public class ContentActivity extends SingleFragmentActivity

{

private ContentFragment mContentFragment;

@Override

protected Fragment createFragment()

{

String title = getIntent().getStringExtra(ContentFragment.ARGUMENT);

mContentFragment = ContentFragment.newInstance(title);

return mContentFragment;

}

}

package com.example.demo_zhy_23_fragments;

import android.support.v4.app.Fragment;

public class ListTitleActivity extends SingleFragmentActivity

{

private ListTitleFragment mListFragment;

@Override

protected Fragment createFragment()

{

mListFragment = new ListTitleFragment();

return mListFragment;

}

}

是不是简洁很多,相信优先使用Fragment的项目,类似的Activity非常多,使用SingleFragmentActivity来简化你的代码吧~~

好了,此代码是来自文章开始推荐的书中的,再次推荐一下~~。

5、FragmentPagerAdapter与FragmentStatePagerAdapter

================================================

相信这两个PagerAdapter的子类,大家都不陌生吧自从Fragment问世,使用ViewPager再结合上面任何一个实例的制作APP主页的案例特别多~

那么这两个类有何区别呢?

主要区别就在与对于fragment是否销毁,下面细说:

FragmentPagerAdapter:对于不再需要的fragment,选择调用detach方法,仅销毁视图,并不会销毁fragment实例。

FragmentStatePagerAdapter:会销毁不再需要的fragment,当当前事务提交以后,会彻底的将fragmeng从当前Activity的FragmentManager中移除,state标明,销毁时,会将其onSaveInstanceState(Bundle outState)中的bundle信息保存下来,当用户切换回来,可以通过该bundle恢复生成新的fragment,也就是说,你可以在onSaveInstanceState(Bundle outState)方法中保存一些数据,在onCreate中进行恢复创建。

如上所说,使用FragmentStatePagerAdapter当然更省内存,但是销毁新建也是需要时间的。一般情况下,如果你是制作主页面,就3、4个Tab,那么可以选择使用FragmentPagerAdapter,如果你是用于ViewPager展示数量特别多的条目时,那么建议使用FragmentStatePagerAdapter。

篇幅原因,具体的案例就不写了,大家自行测试。

6、Fragment间的数据传递

================

上面3中,我们展示了,一般的两个Fragment间的数据传递。

那么还有一种比较特殊的情况,就是两个Fragment在同一个Activity中:例如,点击当前Fragment中按钮,弹出一个对话框(DialogFragment),在对话框中的操作需要返回给触发的Fragment中,那么如何数据传递呢?对于对话框的使用推荐:Android 官方推荐 : DialogFragment 创建对话框

我们继续修改我们的代码:现在是ListTitleFragment , ContentFragment , 添加一个对话框:EvaluateDialog,用户点击ContentFragment 内容时弹出一个评价列表,用户选择评价。

现在我们的关注点在于:ContentFragment中如何优雅的拿到EvaluateDialog中返回的评价:

记住我们在一个Activity中,那么肯定不是使用startActivityForResult;但是我们返回的数据,依然在onActivityResult中进行接收。

好了看代码:

ContentFragment

public class ContentFragment extends Fragment

{

private String mArgument;

public static final String ARGUMENT = “argument”;

public static final String RESPONSE = “response”;

public static final String EVALUATE_DIALOG = “evaluate_dialog”;

public static final int REQUEST_EVALUATE = 0X110;

//…

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState)

{

Random random = new Random();

TextView tv = new TextView(getActivity());

ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(

LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

tv.setLayoutParams(params);

tv.setText(mArgument);

tv.setGravity(Gravity.CENTER);

tv.setBackgroundColor(Color.argb(random.nextInt(100),

random.nextInt(255), random.nextInt(255), random.nextInt(255)));

// set click

tv.setOnClickListener(new OnClickListener()

{

@Override

public void onClick(View v)

{

EvaluateDialog dialog = new EvaluateDialog();

//注意setTargetFragment

dialog.setTargetFragment(ContentFragment.this, REQUEST_EVALUATE);

dialog.show(getFragmentManager(), EVALUATE_DIALOG);

}

});

return tv;

}

//接收返回回来的数据

@Override

public void onActivityResult(int requestCode, int resultCode, Intent data)

{

super.onActivityResult(requestCode, resultCode, data);

if (requestCode == REQUEST_EVALUATE)

{

String evaluate = data

.getStringExtra(EvaluateDialog.RESPONSE_EVALUATE);

Toast.makeText(getActivity(), evaluate, Toast.LENGTH_SHORT).show();

Intent intent = new Intent();

intent.putExtra(RESPONSE, evaluate);

getActivity().setResult(Activity.REQUEST_OK, intent);

}

}

}

删除了一些无关代码,注意看,我们在onCreateView中为textview添加了click事件,用于弹出我们的dialog,注意一行代码:

dialog.setTargetFragment(ContentFragment.this, REQUEST_EVALUATE);

我们调用了Fragment.setTargetFragment ,这个方法,一般就是用于当前fragment由别的fragment启动,在完成操作后返回数据的,符合我们的需求吧~~~注意,这句很重要。

接下来看EvaluateDialog代码:

package com.example.demo_zhy_23_fragments;

import android.app.Activity;

import android.app.AlertDialog;

import android.app.Dialog;

import android.content.DialogInterface;

import android.content.DialogInterface.OnClickListener;

import android.content.Intent;

import android.os.Bundle;

import android.support.v4.app.DialogFragment;

public class EvaluateDialog extends DialogFragment

{

private String[] mEvaluteVals = new String[] { “GOOD”, “BAD”, “NORMAL” };

public static final String RESPONSE_EVALUATE = “response_evaluate”;

@Override

public Dialog onCreateDialog(Bundle savedInstanceState)

{

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

builder.setTitle(“Evaluate :”).setItems(mEvaluteVals,

new OnClickListener()

{

@Override

public void onClick(DialogInterface dialog, int which)

{

setResult(which);

}

});

return builder.create();

}

// 设置返回数据

protected void setResult(int which)

{

// 判断是否设置了targetFragment

if (getTargetFragment() == null)

return;

Intent intent = new Intent();

intent.putExtra(RESPONSE_EVALUATE, mEvaluteVals[which]);

getTargetFragment().onActivityResult(ContentFragment.REQUEST_EVALUATE,

Activity.RESULT_OK, intent);

}

}

重点就是看点击后的setResult了,我们首先判断是否设置了targetFragment,如果设置了,意味我们要返回一些数据到targetFragment。

我们创建intent封装好需要传递数据,最后手动调用onActivityResult进行返回数据~~

最后我们在ContentFragment的onActivityResult接收即可。

实战系列

话不多说,Android实战系列集合都已经系统分类好,由于文章篇幅问题没法过多展示



《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

// 设置返回数据

protected void setResult(int which)

{

// 判断是否设置了targetFragment

if (getTargetFragment() == null)

return;

Intent intent = new Intent();

intent.putExtra(RESPONSE_EVALUATE, mEvaluteVals[which]);

getTargetFragment().onActivityResult(ContentFragment.REQUEST_EVALUATE,

Activity.RESULT_OK, intent);

}

}

重点就是看点击后的setResult了,我们首先判断是否设置了targetFragment,如果设置了,意味我们要返回一些数据到targetFragment。

我们创建intent封装好需要传递数据,最后手动调用onActivityResult进行返回数据~~

最后我们在ContentFragment的onActivityResult接收即可。

实战系列

话不多说,Android实战系列集合都已经系统分类好,由于文章篇幅问题没法过多展示

[外链图片转存中…(img-Bn2fIyDN-1714386400433)]
[外链图片转存中…(img-n8IeC9VV-1714386400434)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值