1.在Fragment中找到getContext()方法如下:
* Return the {@link Context} this fragment is currently associated with.
public Context getContext() {
return mHost == null ? null : mHost.getContext();
2.由上述可知当mHost == null 或者 mHost.getContext() =null
两种情况下会导致返回null.
对此需分析mHost是什么?
(1) Fragment中mHost的变量
// Activity this fragment is attached to.
@UnsupportedAppUsage
FragmentHostCallback mHost;
(2) 查找mHost在什么地方赋值
I.优先参考: [正向调用过程的逻辑梳理]
通过源码解析 Fragment 启动过程
https://www.jianshu.com/p/f2fcc670afd6
获取整体性的认知
II.辅助参考:[逆向结果推原因的逻辑梳理]
Fragment中getContext得到的context从哪来?
https://blog.csdn.net/XG1057415595/article/details/82595248
看如何反推
我们的fragment一般是通过FragmentManager的beginTransaction方法得到FragmentTransaction然后add添加,而我们getSupportFragmentManager获取到
的是FragmentManagerImpl, 也就是FragmentManager的实现类,我们看FragmentManagerImpl的beginTransaction方法:
@Override
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
可以看到我们得到的FragmentTransaction是一个BackStackRecord对象,该类继承自FragmentTransaction;
而BackStackRecord的add方法最终还是回到FragmentManagerImpl的addFragment方法(涉及的fragment启动过程参考上述I);
- 参考:
(1)关于android:为什么片段中的getContext()有时会返回null?
https://www.codenong.com/47987649/
(2)Fragment 中使用 getActivity()为null的原因—剖析源码
https://www.cnblogs.com/tingtasia/p/11545014.html
(2+)Fragment中调用getActivity为null的问题---------------->Activity与Fragment的调用关系
https://blog.csdn.net/ly969434341/article/details/107247332
(3)Android System——事件传递(一) View
https://www.jianshu.com/p/0b05c7fe24f9 - 实验性demo:
参见:FragmentAndActivity.工程 - 一种猜想性推论?
当transition的commit提交到消息队列,未被执行时, Fragment就没有mHost中含有的Activity;
此时若Fragment中的onCreateView等方法执行完毕, button被注册onClickListener;并点击后,点击事件进入到消息队列.
如果先执行了点击的消息就会产生Activity为null的问题.
_ >针对此猜测,并不成立,
_ >因为commit提交在前,点击事件提交在后.在主线程的消息队列中若没有特殊指定延时,会先执行前面提交的事件.
_ >可参考: Android应用程序消息处理机制(Looper、Handler)分析 - (3+)可代码验证的一种问题情况
(1) 由于一个应用中的一个Activity被销毁的时候;该应用进程没有被销毁;
与主线程相关联的消息队列也没有被销毁.
(2) 若之前该button上发生的点击事件进入了消息队列,而没有被消费掉.
(3)此时,该button所在Fragment的Activity,因为(a)旋转配置发生改变,或(b)长时间放置内存不足被系统回收; 销毁后.
(4)当消息队列中,未被消费的消息执行的时候,若消息中含有需要getActivity()这样的逻辑,就会报空指针异常.
(5) 示例代码:
Fragment:
public class BlankFragment extends Fragment {
Button button;
int count = 0;
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
Log.e(TAG, "onViewCreated_savedInstanceState " + savedInstanceState);
Log.e(TAG, "onViewCreated_fragment " + this);
Log.e(TAG, "onViewCreated_activity " + getContext());
button = view.findViewById(R.id.test);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// doSomeThing();
count ++;
Log.e(TAG, "count = " + count);
button.postDelayed(new Runnable() {
@Override
public void run() {
Toast.makeText(getActivity(), "count = " + count, Toast.LENGTH_LONG).show();
}, count * 1000);
@Override
public void onDetach() {
super.onDetach();
Log.e(TAG, "onDetach_fragment " + this);
Log.e(TAG, "onDetach_activity " + getContext());
Log.e(TAG, "onDetach_OnClickListener_before_remove " + getOnClickListener(button));
removeOnClickListener(button);
Log.e(TAG, "onDetach_OnClickListener_after_remove " + getOnClickListener(button));
private <T> Method getDeclaredMethod(Object obj, String methodName) {
Method method = null;
Class clazz = obj.getClass();
while (clazz != Object.class) {
try {
method = clazz.getDeclaredMethod(methodName);
return method;
} catch (Exception e) {
clazz = clazz.getSuperclass();
return null;
private Object getListenerInfo(View view) {
Method method = getDeclaredMethod(view, "getListenerInfo");
method.setAccessible(true);
Object info = null;
try {
info = method.invoke(view);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
return info;
private View.OnClickListener getOnClickListener(View view) {
Object info = getListenerInfo(view);
View.OnClickListener result = (View.OnClickListener)
getFieldValue(info, "mOnClickListener");
return result;
private void removeOnClickListener(View view) {
Object info = getListenerInfo(view);
setFiledValue(info, "mOnClickListener", null);
private Object getFieldValue(Object obj, String fieldName) {
if (obj == null || fieldName.isEmpty()) {
return null;
Class clazz = obj.getClass();
if (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(obj);
} catch (Exception e) {
return null;
private void setFiledValue(Object obj, String fieldName, Object value) {
if (obj == null || fieldName.isEmpty()) {
return;
Class clazz = obj.getClass();
while (clazz != Object.class) {
Field field = null;
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
return;
} catch (Exception e) {
e.printStackTrace();
Activity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(TAG, "MainActivity_onCreate_activity " + this);
setContentView(R.layout.activity_main);
Fragment fragment = new BlankFragment();
Log.e(TAG, "MainActivity_onCreate_new_fragment " + fragment);
addFragmentIfNotExist(getFragmentManager(), fragment);
getMainLooper().getQueue();
private void addFragmentIfNotExist(FragmentManager fm, Fragment f) {
String tag = f.getClass().getName();
Fragment old = fm.findFragmentByTag(tag);
Log.e(TAG, "MainActivity_onCreate_old_fragment " + old);
if (old == null) {
FragmentTransaction transaction = fm.beginTransaction();
transaction.add(android.R.id.content, f, tag);
transaction.commit();
(6) 运行后上述代码, 点击按钮, 旋转屏幕后报的异常问题:
2021-02-09 19:03:06.587 2359-2359/com.test.fragmentandactivity E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.test.fragmentandactivity, PID: 2359
java.lang.NullPointerException: Attempt to invoke virtual method ‘java.lang.String android.content.Context.getPackageName()’ on a null object reference
at android.widget.Toast.(Toast.java:117)
at android.widget.Toast.makeText(Toast.java:280)
at android.widget.Toast.makeText(Toast.java:270)
at com.test.fragmentandactivity.BlankFragment$1
1.run(BlankFragment.java:112) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:201) at android.app.ActivityThread.main(ActivityThread.java:6806) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit
1.run(BlankFragment.java:112)atandroid.os.Handler.handleCallback(Handler.java:873)atandroid.os.Handler.dispatchMessage(Handler.java:99)atandroid.os.Looper.loop(Looper.java:201)atandroid.app.ActivityThread.main(ActivityThread.java:6806)atjava.lang.reflect.Method.invoke(NativeMethod)atcom.android.internal.os.RuntimeInitMethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
(6) 问题的解决方法
(a)对于需要进入到消息队列中执行的代码,不要使用getActivity()去获取Context,而应该直接传递到参数中,使用入参Context.
(b) 对于在Activity或Fragment销毁的时候, 清除button的Listener的修复方法,应该是无效的.
一.Fragment中调用getContext()实际调用了什么?1.在Fragment中找到getContext()方法如下: /** * Return the {@link Context} this fragment is currently associated with. */ public Context getContext() { return mHost == null ? null : mHost.getContext(); }
这两天在研究插件化编程,在使用 Fragment 碰到了一些问题,于是查看源码,顺便分析了一下 Fragment 和 FragmentManager 以及其他几个 API 的原代码,看看他们是怎么工作的。
我们知道 Fragment 有个 onCreateView() 方法,这个方法在 Fragment 创建 View 的时候被调用,并且返回一个 View 对象。那么 onCreateView 在什么时候被调用呢,咱们在 Fragment 这个类里找到了一个方法,performCreateView() 方法。
Fragment.java
public View onCreateView(La
今天在改上一篇中的bug(android.support.v4.app.Fragment$InstantiationException)时又发现了一个问题,经过实验得出结果.
Fragment中获取Activity的Context时只需要this.getActivity()即可.
而不是许多人说的this.getActivity().getApplicationContext()
SecurityContextHolder.getContext().getAuthentication()为null的情况
在登录的时候,用如下方法获取输入的用户名:
* 获得当前用户名称
private String getUsername() {
String username = SecurityContextHolder.getContext().ge...
安卓app有一种特殊情况,就是 app运行在后台的时候,系统资源紧张的时候或者应用出现bug奔溃的时候导致把app的资源全部回收(杀死app的进程),这时把app再从后台返回到前台时,app会重启。这种情况下文简称为:“内存重启”。(屏幕旋转等配置变化也会造成当前Activity重启,本质与“内存重启”类似)
在系统要把app回收之前,系统会把Activity的状态保存下来,Activity的F
Context,中文直译为“上下文”,SDK中对其说明如下:
1、它描述的是一个应用程序环境的信息,即上下文。
2、该类是一个抽象(abstract class)类,Android提供了该抽象类的具体实现类(后面我们会讲到是ContextIml类)。
3、通过它我们可以获取应用程序的资源和类,也包括一些应用级别操作,例如:启动一个Activity,发送广播,接受Intent信息等。
各种context及区别:
1.getApplicationContext() 返回在应用程序运行的所有活动中。
最近在项目中遇到一个问题,在项目中,Fragment中的一个图标,需要在点击缩放动画完成后,跳转到另一个界面,但是经常会出现getActivity()或getContext()方法返回值为空的问题。在网上查找了很多解决方案,大概有以下几种:
1. 根据fragment的生命周期,将方法的调用写到onStart()方法内部。我将方法的调用写到了onResume()方法中,都同样会
Security
ContextHolder.get
Context().getAuthentication() 为
null,这个问题比较难解决,很多都是什么权限问题。
springcloud
中,出现这个问题一般是因为feign的熔断问题导致的。
feign.hystrix.enabled=false
立刻可以解决该问题。
做一个小项目的时候遇到了一个空指针问题, 项目的大概是这样FragmentA中是一些普通布局,FragmentB中是一个listview显示数据,当我从FragmentA中点击 到FragmentB的时,FragmentB中listview还没有把数据加载出来时再次切换到FragmentA就会发现闪退异常空指针
然后我看了一下原因发现FragmentB里的listview适配器中的Conte
Fragment回调顺序
onAttach->onCreate->onCreateView->onActivityCreated
ps:最后发现经常在Fragment里面getActivity()为空,特别是在AsyncTask的onPostExecute里面,解决方案是定义Activity成员变量,然后在onAttach里面赋值
update:上面的ps可以解决空指...
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var can = canvas.getContext("2d");
can.fillStyle = "#990099";
can.fillRect(0, 0, 5...
在Fragment中使用findViewById方法,需要先获取Fragment的根视图,然后再通过根视图调用findViewById方法来查找对应的视图控件。具体步骤如下:
1. 在Fragment的onCreateView方法中,通过LayoutInflater的inflate方法将布局文件转换成View对象,并返回该View对象作为Fragment的根视图。
2. 在Fragment的onViewCreated方法中,通过根视图调用findViewById方法来查找对应的视图控件,并将其赋值给成员变量。
例如,在Fragment中查找一个TextView控件的代码如下:
public class MyFragment extends Fragment {
private TextView mTextView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_layout, container, false);
return rootView;
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mTextView = view.findViewById(R.id.text_view);
在上面的代码中,我们先通过LayoutInflater的inflate方法将布局文件fragment_layout转换成View对象,并将其作为Fragment的根视图返回。
然后,在onViewCreated方法中,我们通过根视图view调用findViewById方法来查找id为text_view的TextView控件,并将其赋值给成员变量mTextView。这样,在Fragment的其他方法中就可以直接使用mTextView来操作TextView控件了。
Cognitive Complexity of methods should not be too high Refactor this method to reduce its Cognitive
32490