前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Fragment基本使用

Fragment基本使用

作者头像
233333
发布于 2021-04-20 02:58:27
发布于 2021-04-20 02:58:27
2K00
代码可运行
举报
运行总次数:0
代码可运行

1. Fragment概述

1.1 介绍

Fragment是一种可以嵌入在活动中的UI片段,能够让程序更加合理和充分地利用大屏幕的空间,出现的初衷是为了适应大屏幕的平板电脑,可以将其看成一个小型Activity,又称作Activity片段。

使用Fragment可以把屏幕划分成几块,然后进行分组,进行一个模块化管理。Fragment不能够单独使用,需要嵌套在Activity中使用,其生命周期也受到宿主Activity的生命周期的影响

官方定义如下:

A Fragment represents a behavior or a portion of user interface in an Activity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and which you can add or remove while the activity is running.

从官方的定义可以得到:

  • Fragment依赖于Activity,不能独立存在
  • 一个Activity可以有多个Fragment
  • 一个Fragment可以被多个Activity重用
  • Fragment有自己的生命周期,并能接收输入事件
  • 可以在Activity运行时动态地添加或删除Fragment

Fragment的优势:

  • 模块化(Modularity):我们不必把所有代码全部写在Activity中,而是把代码写在各自的Fragment中。
  • 可重用(Reusability):多个Activity可以重用一个Fragment。
  • 可适配(Adaptability):根据硬件的屏幕尺寸、屏幕方向,能够方便地实现不同的布局,这样用户体验更好。

1.2 Fragment基本生命周期

Fragment的一般生命周期如上图所示:

  • onAttach():Fragment和Activity相关联时调用。可以通过该方法获取Activity引用,还可以通过getArguments()获取参数。
  • onCreate():Fragment被创建时调用
  • onActivityCreated():当Activity完成onCreate()时调用
  • onStart():当Fragment可见时调用。
  • onResume():当Fragment可见且可交互时调用
  • onPause():当Fragment不可交互但可见时调用。
  • onStop():当Fragment不可见时调用。
  • onDestroyView():当Fragment的UI从视图结构中移除时调用。
  • onDestroy():销毁Fragment时调用。
  • onDetach():当Fragment和Activity解除关联时调用。

Fragment生命周期会经历:运行、暂停、停止、销毁。

  • 运行状态:碎片可见时,关联活动处于运行状态,其也为运行状态
  • 暂停状态:活动进入暂停状态,相关联可见碎片就会进入暂停状态
  • 停止状态:活动进入停止状态,相关联碎片就会进入停止状态,或者通过FragmentTransaction的remove()、replace()方法将碎片从从活动中移除,但如果在事务提交之前调用addToBackStack()方法,这时的碎片也会进入到停止状态。
  • 销毁状态:当活动被销毁,相关联碎片进入销毁状态。或者调用FragmentTransaction的remove()、replace()方法将碎片从活动中移除,但在事务提交之前并没有调用addToBackStack()方法,碎片也会进入到销毁状态。

在介绍Fragment的具体使用时,先介绍一下Fragment的几个核心类

  • Fragment:Fragment的基类,任何创建的Fragment都需要继承该类
  • FragmentManager:管理和维护Fragment。他是抽象类,具体的实现类是FragmentManagerImpl。
  • FragmentTransaction:对Fragment的添加、删除等操作都需要通过事务方式进行。他是抽象类,具体的实现类是BackStackRecord

扩展子类:

  • 对话框:DialogFragment
  • 列表:ListFragment
  • 选项设置:PreferenceFragment
  • WebView界面:WebViewFragment

备注:开发Fragment不建议使用android.app下的Fragment而应是android:support.v4.app,因为support库是不断更新的。

2. Fragment使用

使用Fragment有两种方式,分别是静态加载和动态加载

2.1 静态加载

关于静态加载的流程如下:

  • 定义Fragment的xml布局文件
  • 自定义Fragment类,继承Fragment类或其子类,同时实现onCreate()方法,在方法中,通过inflater.inflate加载布局文件,接着返回其View
  • 在需要加载Fragment的Activity对应布局文件中的name属性设为全限定类名,即包名.fragment
  • 最后在Activity调用setContentView()加载布局文件即可

静态加载一旦添加就不能在运行时删除

示例:

  • 定义Fragment布局,新建left_fragment.xml和right_fragment.xml文件
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Button" />
</LinearLayout>
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="#00ff00"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textSize="20sp"
        android:text="this is Fragment" />

</LinearLayout>
  • 自定义Fragment类,继承Fragment或其子类,重写onCreateView(),在方法中调用inflater.inflate()方法加载Fragment布局文件,接着返回加载的view对象
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class LeftFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.left_fragment, container,false);
        return view;
    }

}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class RigthFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.right_fragment, container, false);
        return view;
    }
}
  • 在需要加载Fragment的Activity对应的布局文件中添加Fragment标签
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<fragment
    android:id="@+id/left_fragment"
    android:name="com.vivo.a11085273.secondfragmenttest.LeftFragment"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1" />
<fragment
    android:id="@+id/right_fragment"
    android:name="com.vivo.a11085273.secondfragmenttest.RigthFragment"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    />
  • 在Activity的onCreate()方法中调用setContentView()加载布局文件即可

2.2 动态加载Fragment

动态加载Fragment的流程如下:

  • 获得FragmentManager对象,通过getSupportFragmentManager()
  • 获得FragmentTransaction对象,通过fm.beginTransaction()
  • 调用add()方法或者repalce()方法加载Fragment;
  • 最后调用commit()方法提交事务

简单示例:

  • 同静态加载一样,首先定义Fragment的布局和类,修改主布局文件,不指定标签的name属性。
  • 实现Fragment调用
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(this);
        replaceFragment(new RigthFragment());
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                replaceFragment(new AnotherRightFragment());
                break;
            default:
                break;
        }
    }

    private void replaceFragment(Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();   // 开启一个事务
        transaction.replace(R.id.right_layout, fragment);
        transaction.commit();
    }
}

2.3 使用注意点

  • Fragment的onCreateView()方法返回Fragment的UI布局,需要注意的是inflate()的第三个参数是false,因为在Fragment内部实现中,会把该布局添加到container中,如果设为true,那么就会重复做两次添加,则会抛如下异常:

Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child’s parent first.

  • 如果在创建Fragment时要传入参数,必须要通过setArguments(Bundle bundle)方式添加,而不建议通过为Fragment添加带参数的构造函数,因为通过setArguments()方式添加,在由于内存紧张导致Fragment被系统杀掉并恢复(re-instantiate)时能保留这些数据

可以在Fragment的onAttach()中通过getArguments()获得传进来的参数。如果要获取Activity对象,不建议调用getActivity(),而是在onAttach()中将Context对象强转为Activity对象

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Fragment1 extends Fragment{
    private static String ARG_PARAM = "param_key";
    private String mParam;
    private Activity mActivity;
    public void onAttach(Context context) {
        mActivity = (Activity) context;
        mParam = getArguments().getString(ARG_PARAM);  //获取参数
    }
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_1, container, false);
        TextView view = root.findViewById(R.id.text);
        view.setText(mParam);
        return root;
    }
    public static Fragment1 newInstance(String str) {
        Fragment1 frag = new Fragment1();
        Bundle bundle = new Bundle();
        bundle.putString(ARG_PARAM, str);
        fragment.setArguments(bundle);   //设置参数
        return fragment;
    }
}
  • 动态加载Fragment中,FragmentTransaction类提供了方法完成增删等操作,完成后调用FragmentTransaction.commit()方法提交修改
    • transaction.add():往Activity里面添加一个片段
    • transaction.remove():从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁
    • transaction.replace():使用另一个Fragment替换当前的,实际上是remove()然后add()的合体
    • transaction.hide():隐藏当前Fragment,仅不可见,不会销毁
    • transaction.show():显示之前隐藏的Fragment
    • detach():会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护
    • attach():重建view视图,附加到UI上并显示。

commit方法一定要在Activity.onSaveInstance()之前调用

commit()操作是异步的,内部通过mManager.enqueueAction()加入处理队列。对应的同步方法为commitNow(),commit()内部会有checkStateLoss()操作,如果开发人员使用不当(比如commit()操作在onSaveInstanceState()之后),可能会抛出异常,而commitAllowingStateLoss()方法则是不会抛出异常版本的commit()方法,但是尽量使用commit(),而不要使用commitAllowingStateLoss()。

  • FragmentManager拥有回退栈(BackStack),类似于Activity的任务栈,如果添加了该语句,就把该事务加入回退栈,当用户点击返回按钮,会回退该事务(回退指的是如果事务是add(frag1),那么回退操作就是remove(frag1));如果没添加该语句,用户点击返回按钮会直接销毁Activity。
  • Fragment常见异常

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1341) at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1352) at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595) at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)

出现原因:commit()在onSaveInstanceState()后调用。

由于onSaveInstanceState()在onPause()之后,onStop()之前调用。onRestoreInstanceState()在onStart()之后,onResume()之前,因此避免出现该异常的方案有:

  • 不要把Fragment事务放在异步线程的回调中
  • 逼不得已时使用commitAllowingStateLoss()

3. Fragment与Activity联动

Fragment和Activity完整的生命周期如上图所示

  1. 当Fragment在Activity的onCreate()中被添加时
  • Activity super.onCreate执行完毕
  • Fragment onAttach
  • Fragment onCreate
  • Fragment onCreateView
  • Fragment onViewCreated
  • Activity.super.onStart()执行中
  • Fragment onActivityCreated
  • Fragment onViewStateRestored
  • Fragment onStart()
  • Activity super.onStart执行完毕
  • Activity super.onPostCreate()
  • Activity super.onResume()
  • Activity super.onPostResume()执行中
  • Fragment onResume()
  • Activity super.onPosResume()执行完毕
  • Activity onAttachedToWindow()
  • Activity onCreateOptionsMenu()
  • Fragment onCreateOptionsMenu()
  • Activity onPrepareOptionsMenu()
  • Fragment onPrepareOptionsMenu()
  • Activity onWindowFocusChanged()
  1. 暂停生命周期
  • Activity super.onPause()执行中
  • Fragment.onPause()
  • Activity super.onPause()执行完毕
  • Activity super.onSaveInstanceState()执行中
  • Fragment onSaveInstanceState()
  • Activity super.onSaveInstanceState()执行完毕
  • Activity super.onStop()执行中
  • Fragment onStop()
  • Activity super.onStop()执行完毕
  1. 销毁的生命周期
  • Activity super.onDestroy()执行中
  • Fragment onDestroyView()
  • Fragment onDestroy()
  • Fragment onDetach()
  • Activity super.onDestroy()执行完毕
  1. 重启的生命周期
  • Activity super.onRestart()
  • Activity super.onStart()执行中
  • Fragment onStart()
  • Activity super.onStart()执行完毕
  • Activity super.onResume()
  • Activity super.onPostResume()执行中
  • Fragment onResume()
  • Activity super.onPosResume()执行完毕
  • Activity onWindowFocusChanged()执行完毕

3.1 回退栈

类似Android系统为Activity维护一个任务栈,我们也可以通过Activity维护一个回退栈来保存每次Fragment事务发生的变化。如果你将Fragment任务添加到回退栈,当用户点击后退按钮时,将看到上一次的保存的Fragment。

一旦Fragment完全从后退栈中弹出,用户再次点击后退键,则退出当前Activity

添加一个Fragment事务到回退栈:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
FragmentTransaction.addToBackStack(String)

简单示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private void replaceFragment(Fragment fragment) {
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.replace(R.id.right_layout, fragment);
    transaction.addToBackStack(null);   //添加进回退栈
    transaction.commit();
}

replace是remove和add的合体,并且如果不添加事务到回退栈,前一个Fragment实例会被销毁。这里很明显,我们调用transaction.addToBackStack(null);将当前的事务添加到了回退栈,所以FragmentOne实例不会被销毁,但是视图层次依然会被销毁,即会调用onDestoryView和onCreateView

如果不希望视图重绘,可以将原来的Fragment隐藏:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private void replaceFragment(Fragment fragment) {
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.hide(this);
    transaction.add(R.id.right_layout, fragment);
    transaction.addToBackStack(null);   //添加进回退栈
    transaction.commit();
}

4. Fragment与Activity通信

Fragment与Activity的通信交互如上图所示:

  • 如果Activity中包含自己管理的Fragment的引用,可以通过引用直接访问所有的Fragment的public方法
  • 如果Activity中未保存任何Fragment的引用,那么没关系,每个Fragment都有一个唯一的TAG或者ID,可以通过getFragmentManager.findFragmentByTag()或者findFragmentById()获得任何Fragment实例,然后进行操作
  • 在Fragment中可以通过getActivity得到当前绑定的Activity的实例,然后进行操作。

备注:

  • 如果在Fragment中需要Context,可以通过getActivity(),如果该Context需要在Activity被销毁后还存在,则使用getActivity.getApplicationContext();

考虑Fragment的重复使用问题,降低与Activity的耦合,Fragment操作应该由它的管理者Activity决定。

4.1 传递数据给Fragment

步骤流程:

  • 在Activity中创建Bundle数据包,调用Fragment实例的setArguments(),将Bundle数据包传给Fragment
  • Fragment调用getArguments()获得Bundle对象,然后进行解析就可以

简单示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//创建Fragment对象,并通过Bundle对象传递值(在onCreate方法中)
MyFragment fragment = new MyFragment();
Bundle bundle = new Bundle();
bundle.putString("key", values);
fragment.setArguments(bundle);
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//(在Fragment类中的onCreateView方法中)
Bundle bundle = this.getArguments();
    if (bundle != null)
    {
        String str = bundle.getString("key");
    }
    TextView textView = new TextView(getActivity());
    textView.setText("上上下下的享受");//是电梯,别误会

4.2 传递数据给Activity

步骤流程:

  • 在Fragment中定义一个内部回调接口,再让包含该Fragment的Activity实现该回调接口
  • Fragment通过回调接口传数据

简单示例:

  • 首先在Fragment中定义一个接口(定义抽象方法,传什么类型参数)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*接口*/  
public interface Mylistener{
    public void thanks(String code);
}
  • Fragment类中定义该接口
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private Mylistener listener;
  • 在onAttach方法中,将定义的该接口强转为activity类型
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
    public void onAttach(Activity activity) {
        // TODO Auto-generated method stub
        listener=(Mylistener) activity;
        super.onAttach(activity);
    }
  • Activity只需实现该接口并重写该方法即可
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
    public void thanks(String code) {
        // TODO Auto-generated method stub
        Toast.makeText(this, "已收到Fragment的消息:--"+code+"--,客气了", Toast.LENGTH_SHORT).show();;
    }

除了接口回调,还可以使用EventBus进行交互通信。

5. Fragment间通信

5.1 setArguments()

示例:

  • 在Fragment B中新建一个函数:newInstance()接收传过来的参数
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static Fragment2 newInstance(String text) {
        Fragment2 fragment = new Fragment2();
        Bundle args = new Bundle();
        args.putString("param", text);
        fragment.setArguments(args);
        return fragment;
    }
  • 在Fragment B的onCreateView中获取参数
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view =  inflater.inflate(R.layout.fragment2, container, false);
        if (getArguments() != null) {
            String mParam1 = getArguments().getString("param");
            TextView tv =  (TextView)view.findViewById(R.id.textview);
            tv.setText(mParam1);
        }
        return view;
    }
  • 在Fragment A中,调用Fragment B时,通过newInstance函数获取实例并传递参数:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Fragment1 extends Fragment {
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment1, container, false);
        Button btn = (Button)view.findViewById(R.id.load_fragment2_btn);
        btn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(final View view) {
                Fragment2 fragment2 = Fragment2.newInstance("从Fragment1传来的参数");
 
                FragmentTransaction transaction = getFragmentManager().beginTransaction();
                transaction.add(R.id.main_layout, fragment2);
                transaction.addToBackStack(null);
                transaction.commit();
            }
        });
        return view;
    }
}

5.2 同Activity不同Container的Fragment交互

这种情况有三中方法解决:

方法一:直接在Activity中操作

​ 直接在Activity中找到对应控件的实例,然后直接操控即可

方法二:直接在Fragment中操作

​ 这里有两个问题:如何获取自己控件的引用?如何获取其他Fragment页控件的引用?

  • 首先获取自己控件的引用

可以在onCreateView()中获取

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment1, container, false);
    listView = (ListView)rootView.findViewById(R.id.list);//获取自己视图里的控件引用,方法一
    return rootView;
}

在onCreateView()中,还没有创建视图,所以在这里如果使用getView()方法将返回空

另一种方法是在onActivityCreated()中获取,其回调在onCreate()执行后再执行

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
 
    listView = (ListView) getView().findViewById(R.id.list);//获取自己视图里的控件引用,方法二
}
  • 获取其它Fragment页控件引用方法

获取Activity资源,须等Activity创建完成后,必须放在onActivityCreated()回调函数中

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
 
    mFragment2_tv = (TextView) getActivity().findViewById(R.id.fragment2_tv);//获取其它fragment中的控件引用的唯一方法!!!
 
}

总的实现示例如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
 
    mFragment2_tv = (TextView) getActivity().findViewById(R.id.fragment2_tv);//获取其它fragment中的控件引用的唯一方法!!!
    listView = (ListView) getView().findViewById(R.id.list);//获取自己视图里的控件引用,方法二
 
    ArrayAdapter arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, mStrings);
    listView.setAdapter(arrayAdapter);
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            String str = mStrings[position];
            mFragment2_tv.setText(str);
       }
    });
}

方法三:在各自Fragment中操作

方法二在Fragment A中操作了Fragment B,违背模块分离思想,应通过Activity将其分离

在Activity中可以直接通过FragmentManager.findFragmentById()获取Fragment实例

示例:

在Fragment2设置TextView函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Fragment2 extends Fragment {
    private TextView mTv;
    …………
    public void setText(String text) {
        mTv.setText(text);
    }
}

在Fragment1 中定义处理方式

  • 定义接口与变量
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private titleSelectInterface mSelectInterface;
 
public interface titleSelectInterface{
    public void onTitleSelect(String title);
}
  • 接口变量赋值

接口给Activity使用,在Activity中给接口变量赋值,在Fragment与Activity关联时,需要强转

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void onAttach(Activity activity) {
    super.onAttach(activity);
 
    try {
        mSelectInterface = (titleSelectInterface) activity;
    } catch (Exception e) {
        throw new ClassCastException(activity.toString() + "must implement OnArticleSelectedListener");
    }
}
  • 调用接口变量
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
 
    listView = (ListView) getView().findViewById(R.id.list);//获取自己视图里的控件引用,方法二
    ArrayAdapter arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, mStrings);
    listView.setAdapter(arrayAdapter);
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            String str = mStrings[position];
            mSelectInterface.onTitleSelect(str);
        }
    });
}
  • 在Activity中实现接口
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MainActivity extends FragmentActivity implements Fragment1.titleSelectInterface {
 
    ……
    
    @Override
    public void onTitleSelect(String title) {
        FragmentManager manager = getSupportFragmentManager();
        Fragment2 fragment2 = (Fragment2)manager.findFragmentById(R.id.fragment2);
        fragment2.setText(title);
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-04-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
c#中多线程同步Lock(锁)的研究以及跨线程UI的操作
本文只针对C#中,多线程同步所用到的锁(lock)作为研究对象。由于想更直观的显示结果,所以,在做demo的时候,就把多线程通过事件操作UI的代码也写了出来,留作备忘和分享吧。
zls365
2020/12/31
1.8K0
【C#异步】异步多线程的本质,上下文流转和同步
    net同僚对于async和await的话题真的是经久不衰,这段时间又看到了关于这方面的讨论,最终也没有得出什么结论,其实要弄懂这个东西,并没有那么复杂,简单的从本质上来讲,就是一句话,async 和await异步的本质就是状态机+线程环境上下文的流转,由状态机向前推进执行,上下文进行环境切换,在状态机向前推进的时候第一次的movenext会将当前线程的环境上下文保存起来,然后由TaskScheduler调度是否去线程池拿新线程执行这个task,等到后续推进到最后的movenext的时候,里面设置好结果,异常之后,回调则需要运行在调用await之前的环境上下文中去,这里说的是环境上下文,而并非是线程,所以当前环境上下文在await之前是A线程的上下文,在遇到await结束之后可能是B线程的环境上下文,并且异步是异步,线程是线程,异步不一定多线程,这两个不是等价的,针对async和await的源码刨析可以看一下之前写的博客https://www.cnblogs.com/1996-Chinese-Chen/p/15594498.html,这篇文章针对源码讲了一部分,可能不是很明了,只讲了async await执行的一个顺序对于环境上下文没有过多的描述,接下来,我会讲一些环境上下文,同步上下文的知识,以及在cs程序中,框架对于同步上下文的封装。
陈显达
2023/03/16
5220
【C#异步】异步多线程的本质,上下文流转和同步
C#线程
线程 ----   线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。   多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。   多线程可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。   在 C# 中,System.Threading.Thread
拾点阳光
2018/05/10
8780
【深入浅出C#】章节5:高级面向对象编程:委托和事件
委托和事件是高级面向对象编程中的重要概念,用于实现程序的灵活性、可扩展性和可维护性。它们在实现回调、事件处理和异步编程等方面发挥着关键作用。 委托允许我们将方法视为一种对象,可以将方法作为参数传递、存储在变量中,并在需要时进行调用。这种能力使得委托非常适合用于实现回调函数,将一个方法传递给另一个方法,使得后者在适当的时候调用前者。委托还支持委托链和多播委托的概念,可以将多个方法链接在一起形成一个委托链,依次执行它们。 事件是委托的一种特殊形式,用于实现观察者模式和事件驱动编程。事件提供了一种简洁和可靠的方式来处理和响应特定的程序事件,如用户交互、消息通知等。通过事件,我们可以定义事件的发布者和订阅者,发布者触发事件时,订阅者会收到通知并执行相应的操作。这种松耦合的设计模式使得程序更具可扩展性和可维护性。 委托和事件在异步编程中也起到重要的作用。它们可以帮助我们处理异步操作的回调和通知,提高程序的响应性和效率。通过将异步操作封装在委托或事件中,我们可以在异步操作完成后执行相应的处理逻辑,而不需要阻塞主线程或进行复杂的线程管理。
喵叔
2023/07/21
7300
C#中Invoke的用法()
一直对invoke和begininvoke的使用和概念比较混乱,这两天看了些资料,对这两个的用法和原理有了些新的认识和理解。
vv彭
2020/12/11
2.3K0
invoke和begininvoke 区别——c#
      https://www.cnblogs.com/worldreason/archive/2008/06/09/1216127.html
vv彭
2020/12/16
2.8K0
invoke和begininvoke 区别——c#
c#跨线程访问控件
任务1和任务2采用两个线程,将每次运算结果显示在lable中,我们先按自己的思路写下看能不能实现。
MaybeHC
2024/04/23
1020
c#跨线程访问控件
谈谈C#中各种线程的使用及注意项~
接下来我们就来学习一下 timer 吧,摇摇脑袋,清醒一下,接下来开始学习....
用户7053485
2020/06/19
1.9K0
异步与多线程——c#
异步这概念刚开始接触的时候,不是那么容易接受,但是需要用的地方还真的挺多的,刚学习的时候,也很懵逼走了不少弯路,所以这里有必要总结一下。 msdn文档:https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/ 官方的简介: *.NET Framework提供了执行异步操作的三种模式: 异步编程模型(APM)模式(也称为IAsyncResult的模式),其中异步操作要求Begin和End方法(例如,BeginWrite和EndWrite异步写入操作)。这种模式不再被推荐用于新开发。有关更多信息,请参阅异步编程模型(APM)。
vv彭
2021/01/07
1.7K0
异步与多线程——c#
C#报错——(Winform) 在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级
“Windows 窗体”使用单线程单元 (STA) 模型,因为“Windows 窗体”基于本机 Win32 窗口,而 Win32 窗口从本质上而言是单元线程。STA 模型意味着可以在任何线程上创建窗口,但窗口一旦创建后就不能切换线程,并且对它的所有函数调用都必须在其创建线程上发生。除了 Windows 窗体之外,.NET Framework 中的类使用自由线程模型。有关 .NET Framework 中的线程的信息,请参见线程处理。
vv彭
2021/03/07
3.5K0
C#中的invoke方法
在用.NET Framework框架的WinForm构建GUI程序界面时,如果要在控件的事件响应函数中改变控件的状态,例如:某个按钮上的文本原先叫“打开”,单击之后按钮上的文本显示“关闭”,初学者往往会想当然地这么写:
全栈程序员站长
2022/08/31
1.7K0
C#之委托如此简单
近期和几位做嵌入式开发的朋友闲聊过程中,一位朋友抱怨到:这C#太难用了,我想在N个窗体(或者是N个用户组件之间)传递值都搞不定,非得要定义一个全局变量来存储,然后用定时器来刷新值,太Low了。我急切的回答道:这很简单,不就是委托的事嘛。那你来一个示例啊:朋友道。此为这篇博客的起因,所以此篇博客对于有c#开发经验的伙伴们那是小菜一喋。
sam dragon
2019/11/12
6330
winform开发 总结1>winform程序使用线程的必要性,以及正确的使用方式
单线程操作在执行耗时任务时会造成界面假死,带来非常差劲的用户体验,有时候甚至会影响到正常的业务执行,使用多线程做相关操作实属不得已之举。
FreeTimeWorker
2020/08/31
8250
C#中的委托和事件 - Part.2
如果你看过了 C#中的委托和事件 一文,我想你对委托和事件已经有了一个基本的认识。但那些远不是委托和事件的全部内容,还有很多的地方没有涉及。本文将讨论委托和事件一些更为细节的问题,包括一些大家常问到的问题,以及事件访问器、异常处理、超时处理和异步方法调用等内容。
张子阳
2018/09/27
2.1K0
子线程与UI线程的通信(委托)
由于项目中存在这样的载入的画面:在界面上有显示载入信息的Label控件和进度条,如果采用单线程则在载入数据的时候UI界面会被锁死,造成假死的感觉。为了给一个更友好的界面,因此有必要引入多线程技术,使得软件更加“人性化”。
SAP梦心
2022/05/07
6450
新学C#线程使用总结建议收藏
线程的使用其实很简单,和JAVA里面差不多,但是还是有很多特别的地方,在C#中的线程,如果要对非线程创建的控件进行操作的话,就会有异常,所以需要使用委托来对其他控件进行操作。
全栈程序员站长
2022/07/15
1650
C#实现多线程的几种方式
多线程是C#中一个重要的概念,多线程指的是在同一进程中同时运行多个线程的机制。多线程适用于需要提高系统并发性、吞吐量和响应速度的场景,可以充分利用多核处理器和系统资源,提高应用程序的性能和效率。
追逐时光者
2024/05/12
1970
C#实现多线程的几种方式
C#基础知识回顾--线程传参
  在不传递参数情况下,一般大家都使用ThreadStart代理来连接执行函数,ThreadStart委托接收的函数不能有参数, 也不能有返回值。如果希望传递参数给执行函数,则可以使用带参数的ParameterizedThreadStart委托, public delegate void ParameterizedThreadStart(Object obj) 可以将要传送给线程函数的信息封装为一个对象,然后调用Thread类的以下构造函数  public Thread (Parameterized
hbbliyong
2018/03/05
8670
C#实例(经典):四路光电开关&激光雷达数据采集和波形图绘制
这篇文章涉及较多C#重要知识点,如果都能看懂,你至少可以算得上入门了!有兴趣的同志可以下载源码调试.
zls365
2020/10/30
1.8K0
C#实例(经典):四路光电开关&激光雷达数据采集和波形图绘制
WinForm多线程修改控件时,提示在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke
但是假如在多线程操作还没完成的时候,我就提前关闭窗体,则会引发InvalidOperationException,提示 “在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke”
跟着阿笨一起玩NET
2020/12/29
2.8K0
推荐阅读
相关推荐
c#中多线程同步Lock(锁)的研究以及跨线程UI的操作
更多 >
LV.1
这个人很懒,什么都没有留下~
目录
  • 1. Fragment概述
    • 1.1 介绍
  • 1.2 Fragment基本生命周期
  • 2. Fragment使用
    • 2.1 静态加载
    • 2.2 动态加载Fragment
    • 2.3 使用注意点
  • 3. Fragment与Activity联动
  • 3.1 回退栈
  • 4. Fragment与Activity通信
    • 4.1 传递数据给Fragment
    • 4.2 传递数据给Activity
  • 5. Fragment间通信
    • 5.1 setArguments()
    • 5.2 同Activity不同Container的Fragment交互
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文