「第一行代码」十三、你还应该掌握的高级技巧

全局获取Context的技巧

活动本身就是一个Context对象

class HttpUtil {
    public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {
        ...
        if (!isNetworkAvailable()) {
            //当检测到网络不存在的时候就给用户一个Toast提示
        }
    }
}

但在HttpUtil类中显然是获取不到Context对象的。想要快速解决问题,可以在sendHttpRequest()方法中添加一个Context参数。

class HttpUtil {
    public static void sendHttpRequest(final Context context, final String address, final HttpCallbackListener listener) {
        ...
        if (!isNetworkAvailable()) {
            //当检测到网络不存在的时候就给用户一个Toast提示
            Toast.makeText(context, "network is unavailable", Toast.LENGTH_SHORT).show();
        }
    }
}

但这种解决方案实际上是推卸责任,将获取Context对象的任务转移给了sendHttpRequest()方法的调用方,至于调用方如何获得Context对象、能否获得Context对象,就撒手不管了。

 

Android提供了一个Application类,每当应用程序启动的时候,系统就会自动将这个类进行初始化。我们可以定制一个自己的Application类,以便于管理程序内一些全局的状态信息,比如说全局Context。

public class Myapplication extends Application {

    private static Context context;

    @Override
    public void onCreate() {
        context = getApplicationContext();
    }

    public static Context getContext() {
        return context;
    }
    
}

重写了父类的onCreate()方法,并通过调用getApplicationContext()方法得到了一个应用程序级别的Context,然后又提供了一个静态的getContext()方法,在这里将刚才获得的Context进行返回。

接下来需要告知系统,当程序启动的时候应该初始化MyApplication类,而不是默认的Application类。在AndroidManifest文件的<application>标签中进行指定即可。

<application
    android:name="com.example.networktext.MyApplication"
    ...>
    ...
</ application>

注意,任何一个项目都只能配置一个Application

至此实现了一种全局获取Context的机制,之后不管想在项目任何地方使用Context,只需要调用MyApplication.getContext()方法即可。

 

class HttpUtil {
    public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {
        ...
        if (!isNetworkAvailable()) {
            //当检测到网络不存在的时候就给用户一个Toast提示
            
            //不再需要通过传参的方式来得到Context对象
            //调用MyApplication.getContext()即可
            Toast.makeText(MyApplication.getContext(), "network is unavailable", Toast.LENGTH_SHORT).show();
        }
    }
}

此时不再需要通过传参的方式来得到Context对象,调用MyApplication.getContext()即可。

 

使用Intent传递对象

Intent可以借助它启动活动、发送广播、启动服务等。在进行上述操作时,还可以在Intent中添加一些附加数据,以达到传值的效果。

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("string_data", "hello");
intent.putExtra("int_data", 100);
startActivity(intent);

调用了Intent的putExtra()方法来添加要传递的数据,之后在SecondActivity中就可以得到这些值。

getIntent().getStringExtra("string_data");
getIntent().getIntExtra("int_data", 0);

 

使用Intent传递对象通常有两种实现方式:Serializable和Parcelable。

Serializable序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。

实现序列化的方法很简单,只需要让一个类实现Serializable接口即可。

public class Person implements Serializable {
    private String name;

    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
}

这里让Person类实现了Serializable接口。

Person person = new Person();
person.setName("Tom");
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("person_data", person);
startActivity(intent);

由于Person类实现了Serializable接口,所以才可以这样写。

接下来在SecondActivity中获取这个对象也很简单。

Person person = (Person) getIntent().getSerializableExtra("person_data");

 

Lambda表达式

Lambda表达式本质上是一种匿名方法,既没有方法名,也即没有访问修饰符和返回值类型,使用它来编写代码将会更加简洁、易读。

如果想在Android项目中使用Lambda表达式或者Java8的特性,需要在app/build.gradle中添加如下配置:

    defaultConfig {
        ...

        jackOptions.enabled = true;
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8;
        targetCompatibility JavaVersion.VERSION_1_8;
    }

传统情况下开启一个子线程的写法:

new Thread(new Runnable() {
    @Override
    public void run() {
        //具体逻辑
    }
}).start();

使用Lambda表达式的写法:

new Thread(() -> {
    //具体逻辑
}).start();

为什么可以这么写呢?

因为Thread类的构造函数接受的参数是一个Runnable接口,而Runnable接口中只有一个待实现的方法

public interface Runnable {
    void run();
}

凡是这种只有一个待实现方法的接口,都可以使用Lambda表达式的写法。

 

通常创建一个类似于上述接口的匿名类实现需要这样写法:

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        //具体实现
    }
};

有了Lambda表达式后可以这样写:

Runnable runnable = () -> {
    //具体实现
};

 

新建一个MyListener接口:

public interface MyListener {
    String doSth(String a, int b);
}

使用Lambda表达式创建MyListener接口的匿名实现写法:

MyListener listener = (String a, int b) -> {
    String result = a + b;
    return result;
}

java还会根据上下文自动推断出Lambda表达式中的参数类型,可以简化为:

MyListener listener = (a, b) -> {
    String result = a + b;
    return result;
}

 

一个具体的例子:

public void hello(MyListener listener) {
    String a = "hello lambda";
    int b = 1024;
    String result = listener.doSth(a, b);
    Log.d("TAG", result);
}

在调用hello()方法时可以这样写:

hello((a, b) -> {
    String result = a + b;
    return result;
});

 

处理点击事件时也可以使用Lambda表达式:

//不实用Lambda表达式
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //处理点击事件
    }
});

//使用Lambda表达式
button.setOnClickListener((v) -> {
    //处理点击事件
});

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值