myactivity.this/getActivity()在Fragment中不可通用的原因

public class NameList extends ListFragment{
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        ArrayAdapter nameList = new ArrayAdapter(getActivity(),R.layout.name_row, R.id.text_example);

    }
}

若将构造器参数中的getActivity()替换为myActivity.this便报错不可resolve。构造器原型为:public ArrayAdapter (Context context, int resource, int textViewResourceId),myActivity.this在Activity的上下文环境里可以解析为Context。

那么,是什么原因使得在Fragment的上下文中不可以把myActivity.this解析为Context呢?

阅读 5.9k
2 个回答

@吉人天相 说的就对
补充一点.

其实你翻一下this在Java中的实现机制更好理解..
在java中 this是通过在非静态方法中添加隐参数的方式实现的.
以你给的代码为例子

编译以后这段代码会变成这样

public class NameList extends ListFragment{
@Override
public void onActivityCreated(NameList this, Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    ArrayAdapter nameList = new ArrayAdapter(getActivity(),R.layout.name_row, R.id.text_example);

}

}

注意看onActivityCreated的参数变化. 通过方法的隐参数传递的this总是指向自身的指针.


内部类中的Parent.this是另一种实现机制

假设你的NameList是MyActivity中的一个内部类的话.
那么编译的时候会在NameList中生成一个

final MyActivity this$0;

这个就是你调用MyActivity.this时候真正使用的对象了.

显然 如果你的NameList不是MyActivity的内部类....你当然调用不到这个this$0对象..也就没有MyActivity.this了....从原理上理解比背概念稍微好一点吧

一个反编译后的demo:

package com.dk.test;

public class Outer {

    private void print() {

    }

    class Inner {
        String str;

        public void print() {
            Outer.this.print();
        }
    }
}

反编译后:

Constant pool:
   #1 = Class              #2             //  com/dk/test/Outer$Inner
   #2 = Utf8               com/dk/test/Outer$Inner
   #3 = Class              #4             //  java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Utf8               str
   #6 = Utf8               Ljava/lang/String;
   #7 = Utf8               this$0
   #8 = Utf8               Lcom/dk/test/Outer;
   #9 = Utf8               <init>
  #10 = Utf8               (Lcom/dk/test/Outer;)V
  #11 = Utf8               Code
  #12 = Fieldref           #1.#13         //  com/dk/test/Outer$Inner.this$0:Lcom/dk/test/Outer;
  #13 = NameAndType        #7:#8          //  this$0:Lcom/dk/test/Outer;
  #14 = Methodref          #3.#15         //  java/lang/Object."<init>":()V
  #15 = NameAndType        #9:#16         //  "<init>":()V
  #16 = Utf8               ()V
  #17 = Utf8               LineNumberTable
  #18 = Utf8               LocalVariableTable
  #19 = Utf8               this
  #20 = Utf8               Lcom/dk/test/Outer$Inner;
  #21 = Utf8               print
  #22 = Methodref          #23.#25        //  com/dk/test/Outer.access$0:(Lcom/dk/test/Outer;)V
  #23 = Class              #24            //  com/dk/test/Outer
  #24 = Utf8               com/dk/test/Outer
  #25 = NameAndType        #26:#10        //  access$0:(Lcom/dk/test/Outer;)V
  #26 = Utf8               access$0
  #27 = Utf8               SourceFile
  #28 = Utf8               Outer.java
  #29 = Utf8               InnerClasses
  #30 = Utf8               Inner
{
  java.lang.String str;
    flags:

  final com.dk.test.Outer this$0;
    flags: ACC_FINAL, ACC_SYNTHETIC

  com.dk.test.Outer$Inner(com.dk.test.Outer);
    flags:
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #12                 // Field this$0:Lcom/dk/test/Outer
;
         5: aload_0
         6: invokespecial #14                 // Method java/lang/Object."<init>
":()V
         9: return
      LineNumberTable:
        line 9: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0      10     0  this   Lcom/dk/test/Outer$Inner;

  public void print();
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #12                 // Field this$0:Lcom/dk/test/Outer
;
         4: invokestatic  #22                 // Method com/dk/test/Outer.access
$0:(Lcom/dk/test/Outer;)V
         7: return
      LineNumberTable:
        line 13: 0
        line 14: 7
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0       8     0  this   Lcom/dk/test/Outer$Inner;
}

注意看这一行

final com.dk.test.Outer this$0;

和这一行

1: getfield      #12                 // Field this$0:Lcom/dk/test/Outer

这个就对应 print方法里那个 Outer.this

只有当你的NameList是myActivity的内部类时才可以用myActivity.this,否则编译器怎么知道myActivity.this指的是myActivity的哪个实例

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题