开启成长之旅!这是我参与「日新计划 12 月更文应战」的第17天,点击查看活动详情

Context定义

Android运用都是运用Java言语来编写的,本质上也是一个目标,那么Activity能够new吗?一个Android程序和一个Java程序,他们最大的区别在哪里?区分界限又是什么呢?其实简单点分析,Android程序不像Java程序相同,随便创立一个类,写个main()方法就能跑了,Android运用模型是根据Activity、Service、BroadcastReceiver等组件的运用设计模式,组件的运行要有一个完整的Android工程环境,在这个环境下,这些组件并不是像一个一般的Java目标new一下就能创立实例的了,而是要有它们各自的上下文环境Context。能够这样讲,Context是保持Android程序中各组件能够正常工作的一个核心功能类。

什么是Context

/**
​
 * Interface to global information about an application environment.  This is
​
 * an abstract class whose implementation is provided by
​
 * the Android system.  It
​
 * allows access to application-specific resources and classes, as well as
​
 * up-calls for application-level operations such as launching activities,
​
 * broadcasting and receiving intents, etc.
 */
public abstract class Context {
   /**
   * File creation mode: the default mode, where the created file can only
   * be accessed by the calling application (or all applications sharing the
   * same user ID).
   * @see #MODE_WORLD_READABLE
   * @see #MODE_WORLD_WRITEABLE
   */
   public static final int MODE_PRIVATE = 0x0000;
  
   public static final int MODE_WORLD_WRITEABLE = 0x0002;
​
   public static final int MODE_APPEND = 0x8000;
​
   public static final int MODE_MULTI_PROCESS = 0x0004;
​
   }
​

以上是Android源码对Context的描绘:

  • 它是运用程序环境的大局信息的接口。
  • 这是一个笼统类,由Android系统提供。
  • 它允许拜访特定于运用程序的资源和类,以及调用运用程序级操作,如发动活动,播送和接纳目的等。

Context效果的具体表现

有了Context这个环境,Android组件才能够正常被创立和调用,所以Context的效果如下:
​
TextView tv = new TextView(getContext());
​
ListAdapter adapter = new SimpleCursorAdapter(getApplicationContext(), ...);
​
AudioManager am = (AudioManager) getContext().
getSystemService(Context.AUDIO_SERVICE);
​
getApplicationContext().getSharedPreferences(name, mode);
​
getApplicationContext().getContentResolver().query(uri, ...);
​
getContext().getResources().getDisplayMetrics().widthPixels * 5 / 8;
​
getContext().startActivity(intent);
​
getContext().startService(intent);
​
getContext().sendBroadcast(intent);

Context类的族谱

Framework系统资源——Context的使用与族谱分析

从图中能够看出,Activtiy、Service、Application的最基类都是Context。

Framework系统资源——Context的使用与族谱分析

context运用

context相关函数

//回来一个空 context, 这只能用于高等级(在 main 或顶级请求中),作为context的根节点
context.Background() Context
//回来一个空的 context,不知道用什么的时候就上这个
context.TODO() Context
context.WithValue(parent Context, key, val interface{}) (ctx Context, cancel CancelFunc)
context.WithCancel(parent Context) (ctx Context, cancel CancelFunc)
context.WithDeadline(parent Context, d time.Time) (ctx Context, cancel CancelFunc)
context.WithTimeout(parent Context, timeout time.Duration) (ctx Context, cancel CancelFunc)

context相关运用

Done方法撤销

func Stream(ctx context.Context, out chan<- Value) error {
  for {
    v, err := DoSomething(ctx)
    if err != nil {
      return err
     }
    select {
    case <-ctx.Done():
      return ctx.Err()
    case out <- v:
     }
   }
}

WithValue传值

func main() {
  ctx, cancel := context.WithCancel(context.Background())
  valueCtx := context.WithValue(ctx, key, "add value")
  go watch(valueCtx)
  time.Sleep(10 * time.Second)
  cancel()
  time.Sleep(5 * time.Second)
}
func watch(ctx context.Context) {
  for {
    select {
    case <-ctx.Done():
      //get value
      fmt.Println(ctx.Value(key), "is cancel")
      return
    default:
      //get value
      fmt.Println(ctx.Value(key), "int goroutine")
      time.Sleep(2 * time.Second)
     }
   }
}

WithTimeout超时撤销

package main
import (
  "fmt"
  "sync"
  "time"
  "golang.org/x/net/context"
)
var (
  wg sync.WaitGroup
)
func work(ctx context.Context) error {
  defer wg.Done()
  for i := 0; i < 1000; i++ {
    select {
    case <-time.After(2 * time.Second):
      fmt.Println("Doing some work ", i)
    // we received the signal of cancelation in this channel
    case <-ctx.Done():
      fmt.Println("Cancel the context ", i)
      return ctx.Err()
     }
   }
  return nil
}
func main() {
  ctx, cancel := context.WithTimeout(context.Background(), 4*time.Second)
  defer cancel()
  fmt.Println("Hey, I'm going to do some work")
  wg.Add(1)
  go work(ctx)
  wg.Wait()
  fmt.Println("Finished. I'm going home")
}

WithDeadline截止时刻

package main
import (
  "context"
  "fmt"
  "time"
)
func main() {
  d := time.Now().Add(1 * time.Second)
  ctx, cancel := context.WithDeadline(context.Background(), d)
  defer cancel()
  select {
  case <-time.After(2 * time.Second):
    fmt.Println("oversleep")
  case <-ctx.Done():
    fmt.Println(ctx.Err())
   }
}

文末

一个Activity就是一个Context,一个Service也是一个Context。Android程序员把“场景”笼统为Context类,他们以为用户和操作系统的每一次交互都是一个场景,比方打电话、发短信,这些都是一个有界面的场景,还有一些没有界面的场景,比方后台运行的服务(Service)。

一个运用程序能够以为是一个工作环境,用户在这个环境中会切换到不同的场景,这就像一个前台秘书,她或许需要接待客人,或许要打印文件,还或许要接听客户电话,而这些就称之为不同的场景,前台秘书能够称之为一个运用程序。