Fragment,Activity生命周期、交互、通信和Annotations的那些的常见的坑

3 篇文章 0 订阅
1 篇文章 0 订阅

一. Activity、Fragment、Service和普通的Java类的区别

大家都知道,Java面向对象编程是Android开发的基础,Activity、Fragment,Service,Application本质也是Java类,所以大家在开发的时候总会用Java开发思想,去New 一个对象,然后调用其方法。首先,我必须指出,拥有这样的想法是一件极其危险的事情,很容易为自己留下一些大坑。为了很好的完成类与类之间的交互,我们必须了解Activity、Fragment、Service和普通的Java类的区别:

  1. Activity、Fragment,Service,Application是拥有生命周期的,这是区别于Java类的最大不同点,这就意味着所有与生命周期相关的方法,你在其它的类中是不能调用的【我这里是说与生命周期有关,不仅仅是生命周期方法】;
  2. Activity、Service,Application都是Context的子类,本身自带Android环境,Fragment可以getActivity()获得Context,而其他的Java类只有在Activity、Service,Fragment中实例化时,才能间接的得到Context对象,当然也可以从全局的Application中获取Context;
  3. Activity,Service,Fragment都有其特定的调用的参数传递方法,不能简单自己交互。

二、 Activity的隐式调用和显示调用

Activity和Activity的交互的方法很多,可以隐式调用Activity,也可以显示调用,还可以通过startActivityForResult()会跳;
Intent分为两种:

显式Intent(Explicit intent):通过指定Intent组件名称来实现的,它一般用在知道目标组件名称的前提下,一般是在相同的应用程序内部实现的。

隐式Intent(Implicit intent):通过Intent Filter来实现的,它一般用在没有明确指出目标组件名称的前提下,一般是用于在不同应用程序之间

  1. startActivity()显示调用
Intent intent=new Intent(MainActivity.this,SettingActivity.class);
intent.putExtra(EXTRA,contentEditText.getText().toString());
startActivity(intent);

2.startActivityForResult显示调用

startActivityForResult(Intent intent, Int requestCode)
setResut(int resultCode, Intent intent)
onActivityResult(int requestCode, int resultCode, Intent intent)

3.隐式调用:不是明确指定启动哪个Activity,而是在Intent Filter中设置Action、Data、Category,让系统来筛选出合适的Activity。
如:

// 实例化Intent  
Intent intent = new Intent();  
//设置Intent的Action属性  
intent.setAction("android.intent.action.SEND");  
// 启动Activity  
startActivity(intent);  

action可以增加多个,那么如果有多个Activity都被匹配到了,则系统会弹出一个列出所有已被匹配到的应用程序的列表选项。对于显示Intent,Android不需要去做解析,因为目标组强调内容件很明确。而隐式Intent需要通过解析,将Intent映射给可以处理该Intent的Activity,Service等。Intent的解析机制主要是通过查找已经注册在AndroidManifest.xml中的所有Intent Filter以及其中定义的action,最终找到匹配的Intent。

三.Activity添加Fragment

Activity添加Fragment有两种方式:静态添加和动态添加
1.静态添加:直接在Activity的xml文件中申明,其中name属性指定添加的Fragment。

<fragment android:id="@+id/fragment"
        android:name="com.hp.classes.education.teacher.activity.InteractCompareImageFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

2.动态添加:在Activity文件中添加,可以通过Add(),replace()添加

public void switchToCorrectStudentQuestion(String classId,long examinationId,int edid,int currentCorrected,int total){
        CorrectStudentQuestionFragment mCorrectHomeworkFragment = new CorrectStudentQuestionFragment_();
        Bundle bundle = new Bundle();
        bundle.putString("classId", classId);
        bundle.putLong("examinationId", examinationId);
        bundle.putInt("edid", edid);
        bundle.putInt("currentCorrected", currentCorrected);
        bundle.putInt("total", total);
        mCorrectHomeworkFragment.setArguments(bundle);
        Log.d(TAG, "switchToCorrectStudentQuestion");
        getSupportFragmentManager().beginTransaction().replace(R.id.details_frame, mCorrectHomeworkFragment)
        .commit();
    }

Fragment添加坑一:静态添加和动态添加杂糅
在Activity的xml文件已经申明,又在Activity中通过replace添加,new了两个Fragment,第二次实例化的时候将第一次数据覆盖【清除】,造成空指针异常

四,Activity,Fragment和Adapter进行交互

1.Adapter和Adapter的所有者的交互

无论我们是使用ListView,GridView系列还是RecyclerView,Adapter都是我们避不开的话题。如果仅仅是简单的数据填充,我们通过setAdapter()就完成了两者的交互。但是我们会遇到这样的情况,item中的一些View的操作会影响Activity和Fragment,比如点击ListView的item,获取item中TextView的值填充到Activity或Fragment中的TextView中。
错误思维: 在Fragment中写一个updateTextView(String msg)方法,然后在Adapter中New一个Fragment,然后调用其updateTextView(String msg)方法。
错误原因: 1.Fragment拥有生命周期;2.没有考虑到Fragment中TextView是否绑定成功,导致空指针异常。
正确思路:
1.定义一个接口OnUpdateUI,接口创建一个updateTextView(String msg)方法;
2.让Fragment或Activity实现该接口OnUpdateUI
3.在Adapter创建一个OnUpdateUI接口对象 mOnUpdateUI,并提供getOnUpdateUI()setOnUpdateUI(OnUpdateUI mOnUpdateUI)方法;
4.在Fragment和Activity中创建Adapter对象mAdapter的时候,Adapter调用mAdapter.setOnUpdateUI(this)
5.在Adapter点击item时,调用mOnUpdateUI.updateTextView(String msg)即可

2.Adapter和与Adapter无关的Fragment和Activity交互

其中我们在Adapter调用其他的Activity是很简单的,和Activity的其他打开方式相同,Fragment就要注意了。替换成Fragment可以在Adapter中进行,也可以在Adapter所在的Fragment或是Activity中进行Fragment替换。

五、Fragment之间的交互

使用场景:一个Frament去更新另一个Fragment的UI:【项目使用MVP】比如在项目中,批改FragmentB和批改进度FragmentA在不同的Fragment中,当一个学生批改完成后,FragmentB会调用P向服务器更新数据,在数据更新成功时,调用FragmentB 的V更新批改进度,FragmnetB再更新另一个Fragment的批改进度。
神坑:直接在FragmentB中New FragmentA,然后调用其方法
解决方案:
1.写一个更新进度的接口

public interface CorrectProgressListener {

    /**
     * 更新Progress值
     * @param progress 进度值
     * @param current  当前批改已批改学生数
     * @param total    学生总人数
     */ 
     void updateProgress(int progress, int current, int total);

}

2.在更新进度的FragmentA中实现该接口,在批改FragmentB中的V继承该接口,然后在FragmentB中实现给接口,在Activity中也实现该接口;
3.在FragmentB中拿到Activity的实例,并强转为CorrectProgressListener,然后调用其updateProgress方法。

CorrectProgressListener mCorrectProgressListener;

@Override
public void onResume() {
  super.onResume();
  if (getActivity() instanceof CorrectProgressListener) {
            mCorrectProgressListener = (CorrectProgressListener) getActivity();

        }
    }

@Override
public void updateProgress(int progress, int current, int total) {
        mCorrectProgressListener.updateProgress(progress, current, total);



    }

4.在Activity中通过getSupportFragmentManager().findFragmentById(R.id.details_frame);找到FragmentA,并调用其updateProgress方法,更新进度条

    @Override
    public void updateQuestionDatas(String classId, long examinationId,
            int edid, int currentCorrected, int total) {
        CorrectStudentQuestionFragment  mCorrectStudentQuestionFragment = (CorrectStudentQuestionFragment) getSupportFragmentManager().findFragmentById(R.id.details_frame);
        if (mCorrectStudentQuestionFragment!=null) {
            mCorrectStudentQuestionFragment.updateQuestionDatas(classId, examinationId, edid, currentCorrected, total);
        }
        else{
            switchToCorrectStudentQuestion(classId, examinationId, edid, currentCorrected, total);
        }
//      
    }

六、Fragment回退栈以及生命周期的调用

1.如果我们想把Fragment像Activity一样添加到回退栈,需要调用ft.addToBackStack(null)方法,注意这里为null只是没有标识这个回退栈,并不是表示没有加入回退栈。如果不想加入回退栈就不调用该方法
2.我们知道如果一个Activity看不到,就会调用onPause();但是Fragment看不到时,并不会调用onPause()方法,只有当Activity进入onPause时才会调用Fragment的onPause()生命周期。我们可以通过replace()和remove()方法将Fragment从Activity中移除,如果该Fragment通过addToBackStack添加到回退栈中,就会执行onPause()、onStop()、onDestoryView()方法,如果没有添加到回退栈,还会执行onDestory()和onDetach()方法。

七、DialogFragment不适用的场所

DialogFragment和我们Activity配合的更加默契,便于自定义风格和填充内容,而且在横竖屏切换的不会消失。DialogFragment如果对话框大小确定,使用还是很不错的,但是如果在DialogFragment又添加View就不是很好,会弹出多次形状不同的对话框,最开始是DialogFragment自身的对话框,在添加View之后显示View形状和内容。

八、Android annotations在Fragment,Activity中使用的一些坑

Android annotations让我们更注重于逻辑,帮我们完成了控件的绑定。但是如果不清楚注解函数和Fragment,Activity生命周期的关系,那么坑就会接踵而来
1.在使用annotations后,annotations会自动为我们生成以“_”结尾的子类,我们在使用这个类的时候一定要实例化子类而不是父类;
2.如果xml文件中调用使用注解的Java类,一定要使用带“_”的子类,包括Activity在注册;
3.不要在Activity中操作UI控件,可能控件还没有绑定成功。要在@AfterViews注解的方法操作UI。下面是一个注解生成的Fragment类,控件绑定是在afterSetContentView_()中实现的,而afterSetContentView_()在Fragment中onViewCreated()生命周期中,所以在onViewCreated()之前操作UI控件都是空指针,在onViewCreated()可能也会空指针,所以要在其后操作UI;Activity中UI绑定在onCreate()方法中,同理也只能在其后操作UI

//
// DO NOT EDIT THIS FILE, IT HAS BEEN GENERATED USING AndroidAnnotations.
//


package com.hp.classes.education.teacher.homework.fragment;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import com.googlecode.androidannotations.api.BackgroundExecutor;
import com.hp.classes.education.teacher.activity.R.layout;

public final class CorrectStudentQuestionFragment_
    extends CorrectStudentQuestionFragment
{

    private View contentView_;

    private void init_(Bundle savedInstanceState) {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        init_(savedInstanceState);
        super.onCreate(savedInstanceState);
    }

    private void afterSetContentView_() {
        mWebView = ((WebView) findViewById(com.hp.classes.education.teacher.activity.R.id.student_exam_answer_webview));
        mLoadingView = ((View) findViewById(com.hp.classes.education.teacher.activity.R.id.custom_dialog));
        mBar = ((SeekBar) findViewById(com.hp.classes.education.teacher.activity.R.id.seekBar));
        layout_frame_painter = ((FrameLayout) findViewById(com.hp.classes.education.teacher.activity.R.id.ontest_frame2));
        mNoDataView = ((View) findViewById(com.hp.classes.education.teacher.activity.R.id.nodata));
        parentView = ((LinearLayout) findViewById(com.hp.classes.education.teacher.activity.R.id.ontest_linearlayout2));
        rootView = ((FrameLayout) findViewById(com.hp.classes.education.teacher.activity.R.id.root_layout));
        scoreTv = ((TextView) findViewById(com.hp.classes.education.teacher.activity.R.id.score));
        mContentView = ((View) findViewById(com.hp.classes.education.teacher.activity.R.id.loading_content_layout));
        right = ((TextView) findViewById(com.hp.classes.education.teacher.activity.R.id.correct_right));
        corrected_iv = ((ImageView) findViewById(com.hp.classes.education.teacher.activity.R.id.corrected_iv));
        name = ((TextView) findViewById(com.hp.classes.education.teacher.activity.R.id.student_name_txt));
        wrong = ((TextView) findViewById(com.hp.classes.education.teacher.activity.R.id.correct_wrong));
        mSpecialQuestionCB = ((CheckBox) findViewById(com.hp.classes.education.teacher.activity.R.id.spe_cb));
        head = ((ImageView) findViewById(com.hp.classes.education.teacher.activity.R.id.student_picture));
        questionNum = ((TextView) findViewById(com.hp.classes.education.teacher.activity.R.id.exam_catetory_num));
        {
            View view = findViewById(com.hp.classes.education.teacher.activity.R.id.correct_pre);
            if (view!= null) {
                view.setOnClickListener(new OnClickListener() {


                    @Override
                    public void onClick(View view) {
                        CorrectStudentQuestionFragment_.this.onClick(view);
                    }

                }
                );
            }
        }
        {
            View view = findViewById(com.hp.classes.education.teacher.activity.R.id.correct_next);
            if (view!= null) {
                view.setOnClickListener(new OnClickListener() {


                    @Override
                    public void onClick(View view) {
                        CorrectStudentQuestionFragment_.this.onClick(view);
                    }

                }
                );
            }
        }
        {
            View view = findViewById(com.hp.classes.education.teacher.activity.R.id.correct_right);
            if (view!= null) {
                view.setOnClickListener(new OnClickListener() {


                    @Override
                    public void onClick(View view) {
                        CorrectStudentQuestionFragment_.this.onClick(view);
                    }

                }
                );
            }
        }
        {
            View view = findViewById(com.hp.classes.education.teacher.activity.R.id.correct_wrong);
            if (view!= null) {
                view.setOnClickListener(new OnClickListener() {


                    @Override
                    public void onClick(View view) {
                        CorrectStudentQuestionFragment_.this.onClick(view);
                    }

                }
                );
            }
        }
        initView();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        contentView_ = super.onCreateView(inflater, container, savedInstanceState);
        if (contentView_ == null) {
            contentView_ = inflater.inflate(layout.item_correct_exam, container, false);
        }
        return contentView_;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        afterSetContentView_();
    }

    public View findViewById(int id) {
        if (contentView_ == null) {
            return null;
        }
        return contentView_.findViewById(id);
    }

    public static CorrectStudentQuestionFragment_.FragmentBuilder_ builder() {
        return new CorrectStudentQuestionFragment_.FragmentBuilder_();
    }

    @Override
    public void showToast() {
        BackgroundExecutor.execute(new Runnable() {


            @Override
            public void run() {
                try {
                    CorrectStudentQuestionFragment_.super.showToast();
                } catch (RuntimeException e) {
                    Log.e("CorrectStudentQuestionFragment_", "A runtime exception was thrown while executing code in a runnable", e);
                }
            }

        }
        );
    }

    public static class FragmentBuilder_ {

        private Bundle args_;

        private FragmentBuilder_() {
            args_ = new Bundle();
        }

        public CorrectStudentQuestionFragment build() {
            CorrectStudentQuestionFragment_ fragment_ = new CorrectStudentQuestionFragment_();
            fragment_.setArguments(args_);
            return fragment_;
        }

    }

}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值