Framework系统资源——Context的使用与族谱分析
Context定义
Android应用都是使用Java语言来编写的,本质上也是一个对象,那么Activity可以new吗?一个Android程序和一个Java程序,他们最大的区别在哪里?划分界限又是什么呢?其实简单点分析,Android程序不像Java程序一样,随便创建一个类,写个main()方法就能跑了,Android应用模型是基于Activity、Service、BroadcastReceiver等组件的应用设计模式,组件的运行要有一个完整的Android工程环境,在这个环境下,这些组件并不是像一个普通的Java对象new一下就能创建实例的了,而是要有它们各自的上下文环境Context。可以这样讲,Context是维持Android程序中各组件能够正常工作的一个核心功能类。
45c636374234e194de7924b083475052.jpeg
什么是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类的族谱
image.png从图中可以看出,Activtiy、Service、Application的最基类都是Context。
image.png
Context其实就是提供了一个代码执行的环境,比如Activity,就是提供了Activity中代码的执行环境,因此它持有着该环境中的所有成员信息和函数。
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)。更多framework学习进阶;带你学习framework深层技术。
一个应用程序可以认为是一个工作环境,用户在这个环境中会切换到不同的场景,这就像一个前台秘书,她可能需要接待客人,可能要打印文件,还可能要接听客户电话,而这些就称之为不同的场景,前台秘书可以称之为一个应用程序。