关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » 安卓开发 »Android工具箱之Context解析

    Android工具箱之Context解析

    2016-01-13 00:00:00 出处:philo.top
    分享

    这几天一直在思考一个问题,为什么国内的热门博客和热门教程都是很久之前的,例如我向学习EventBus,不论是鸿洋的博文还是其他论坛,几乎清一色的OnEvent,或者比如我想学习Dagger2,文章数量更是少之又少,关键大量还是Dagger1的内容。

    基于此,外加上看到CodePath公司整合的Android资源正好符合实际需求,所以特意在sg开辟专栏,希望大家能够喜欢,在此申明下,因为工作量巨大,我非常有幸能够同@xixicat一起翻译这一专题,也恳请大家,如遇到任何翻译错误,请指正,可评论中注明,也可电邮我,同时假如某位志趣相投人士有兴趣参与翻译,也可电邮我,我会进一步联系你:neuyuandaima@gmail.com。

    废话不多说,那么我们就开始吧。

    动机

    你有多少次在StackOverflow中寻找答案时,发现其答案竟然是2年前的,你又有多少次搜出的博文是几年前的旧文呢,我相信绝大部分的你都有这样的经历,所以我们为什么不能利用社交让我们的的Android文档布满每个细节呢。

    初篇之Context初探

    概述

    Context对象可以获取应用状态的信息,其使得activitys和Fragments以及Services能够使用资源文件,图片,主题,以及其他的文件夹内容。其也可以用于使用Android自带服务,例如inflate,键盘,以及content providers。

    很多情况下,当你需要用到Context的时候,你肯定只是简单的利用当前activity的实例this。当你一个被activity创建的内部对象的时候,例如adapters里或者fragments里的时候,你需要将activity的实例传给它们。而当你在activity之外,例如application或者service的时候,我们需要利用application的context对象代替。

    Contex的用途

    明确地启动一个组件,例如activity或者service

    Intent intent = new Intent(context, MyActivity.class);
    startActivity(intent);

    创建视图

    TextView textView = new TextView(context);

    Contexts包含了以下信息:

    设备的屏幕大小以及将dp,sp转化为px的尺寸。 style属性 onClick属性

    inflate xml布局文件

    我们使用context来获得LayoutInflater,其可以在内存中inflate xml布局文件

    LayoutInflater inflater = LayoutInflater.from(context);
    inflater.inflate(R.layout.my_layout, parent);

    发送本地广播

    我们使用context来获得LocalBroadcastManager,其可以发送或者注册广播接收。

    Intent broadcastIntent = new Intent("custom-action");
    LocalBroadcastManager.getInstance(context).sendBroadcast(intent);

    获取系统服务

    例如当你需要发送通知,你需要NotificationManager。

    NotificationManager manager = 
        (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    
    int notificationId = 1;
    
    // Context is required to construct RemoteViews
    Notification.Builder builder = 
        new Notification.Builder(context).setContentTitle("custom title");
    
    notificationManager.notify(notificationId, builder.build());

    在此就不一一列举系统服务了, 系统服务列表 参见。

    应用级别的Context和Activity级别的Context

    当主题被运用在应用层面,其也可被运用在activity层面,比如当应用层面定义了一些主题,activity可以将其覆盖。

    <application
           android:allowBackup="true"
           android:icon="@mipmap/ic_launcher"
           android:label="@string/app_name"
           android:theme="@style/AppTheme" >
           <activity
               android:name=".MainActivity"
               android:label="@string/app_name"
               android:theme="@style/MyCustomTheme">

    大部分视图需要传入activity级别的Context对象,这样其才能获取主题,styles,dimensions等属性。假如某个控件没有使用theme,其默认使用了应用的主题。

    在大部分情况下,你需要使用activity级别的Context。通常,关键字this代表着一个类的实例,其可被用于activity中的Context传递。例如:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);  
            Toast.makeText(this, "hello", Toast.LENGTH_SHORT).show();
        }
    }

    匿名方法

    当我们使用了匿名内部类的适合,例如实现监听,this关键字的使用:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
    
            TextView tvTest = (TextView) findViewById(R.id.abc);
            tvTest.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View view) {
                      Toast.makeText(MainActivity.this, "hello", Toast.LENGTH_SHORT).show();
                  }
              });
            }
        }

    适配器

    数组适配器

    当你为listview定义适配器的适合,getContext()方法被经常使用,其用来实例化xml布局。

    if (convertView == null) {
          convertView = 
              LayoutInflater
                  .from(getContext())
                  .inflate(R.layout.item_user, parent, false);
       }

    注意:当你传入的是应用级别的context,你会发现themes/styles属性将不会被应用,所以确保你在这里传入的是Activity级别的context。

    RecyclerView适配器

    public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder> {
    
        @Override 
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View v = 
                LayoutInflater
                    .from(parent.getContext())
                    .inflate(itemLayout, parent, false);
    
            return new ViewHolder(v);
        }
    
        @Override
        public void onBindViewHolder(ViewHolder viewHolder, int i) {
            // If a context is needed, it can be retrieved 
            // from the ViewHolder's root view.
            Context context = viewHolder.itemView.getContext();
    
            // Dynamically add a view using the context provided.
            if(i == 0) {
                TextView tvMessage = new TextView(context);
                tvMessage.setText("Only displayed for the first item.")
    
                viewHolder.customViewGroup.addView(tvMessage);
            }
        }
    
       public static class ViewHolder extends RecyclerView.ViewHolder {
           public FrameLayout customViewGroup;
    
           public ViewHolder(view imageView) {
               super(imageView);
    
               // Perform other view lookups.
               customViewGroup = (FrameLayout) imageView.findById(R.id.customViewGroup);
           }
       }
    }

    可以看到,ArrayAdapter需要在其构造器里面传入context,RecyclerView.Adapter不需要。

    RecyclerView通常将其作为父视图传给RecyclerView.Adapter.onCreateViewHolder()。

    假如在onCreateViewHolder()方法的外面,你需要用到context,你也可以使用ViewHolder,例如viewHolder.itemView.getContext()。itemView是一个公有,非空,final类型的成员变量。

    避免内存泄露

    应用级别的context通常在单例中使用,例如一个常用的管理类,其管理Context对象来获取系统服务,但是其不能同时被多个activity获取。由于维护一个activity级别的context引用会导致内存泄露,所以你需要使用application级别的context替代。

    在下面这个例子中,假如context是activity级别或者service级别,当其被destroy,其实际不会被gc, 因为CustomManager类拥有了其static应用。

    pubic class CustomManager {
        private static CustomManager sInstance;
    
        public static CustomManager getInstance(Context context) {
            if (sInstance == null) {
    
                // This class will hold a reference to the context
                // until it's unloaded. The context could be an Activity or Service.
                sInstance = new CustomManager(context);
            }
    
            return sInstance;
        }
    
        private Context mContext;
    
        private CustomManager(Context context) {
            mContext = context;
        }
    }

    适当地存储context:利用应用级别context

    为了避免内存泄露,不要在其生命周期以外持有该对象。检查你的非主线程,pending handlers或者内部类是否持有context对象。

    存储应用级别的context的最好的办法是CustomManager.getInstance(),其为单例,生命周期为整个应用的进程。

    public static CustomManager getInstance(Context context) {
        if (sInstance == null) {
    
            // When storing a reference to a context, use the application context.
            // Never store the context itself, which could be a component.
            sInstance = new CustomManager(context.getApplicationContext());
        }
    
        return sInstance;
    }

    参考

    What is a context – Simple Code Stuffs Context, what context – Possible Mobile Context: What, where, & how – 101 Apps What is a context – Stack Overflow Avoiding memory leaks
    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    抖音安全与信任开放日:揭秘推荐算法,告别单一标签依赖

    ultraedit编辑器打开文件时,总是提示是否转换为DOS格式,如何关闭?

    Cornell大神Kleinberg的经典教材《算法设计》是最好入门的算法教材

    从 Microsoft 下载中心安装 Windows 7 SP1 和 Windows Server 2008 R2 SP1 之前要执行的步骤

    Llama 2基于UCloud UK8S的创新应用

    火山引擎DataTester:如何使用A/B测试优化全域营销效果

    腾讯云、移动云继阿里云降价后宣布大幅度降价

    字节跳动数据平台论文被ICDE2023国际顶会收录,将通过火山引擎开放相关成果

    这个话题被围观超10000次,火山引擎VeDI如此解答

    误删库怎么办?火山引擎DataLeap“3招”守护数据安全

    IT头条

    平替CUDA!摩尔线程发布MUSA 4性能分析工具

    00:43

    三起案件揭开侵犯个人信息犯罪的黑灰产业链

    13:59

    百度三年开放2.1万实习岗,全力培育AI领域未来领袖

    00:36

    工信部:一季度,电信业务总量同比增长7.7%,业务收入累计完成4469亿元

    23:42

    Gartner:2024年全球半导体营收6559亿美元,AI助力英伟达首登榜首

    18:04

    技术热点

    iOS 8 中如何集成 Touch ID 功能

    windows7系统中鼠标滑轮键(中键)的快捷应用

    MySQL数据库的23个特别注意的安全事项

    Kruskal 最小生成树算法

    Ubuntu 14.10上安装新的字体图文教程

    Ubuntu14更新后无法进入系统卡在光标界面解怎么办?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。