Android进阶之路Android技术知识

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

2022-07-13  本文已影响0人  码农的地中海

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的描述:

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深层技术。

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

上一篇下一篇

猜你喜欢

热点阅读