adb shell input keyevent <keycode> 命令,不同的 keycode 能实现不同的功能。
| keycode | 含义 |
|---|---|
| 3 | HOME 键 |
| 4 | 返回键 |
| 187 | 切换应用 |
adb shell input keyevent <keycode> 命令,不同的 keycode 能实现不同的功能。
| keycode | 含义 |
|---|---|
| 3 | HOME 键 |
| 4 | 返回键 |
| 187 | 切换应用 |
Button继承自TextView,ImageButton继承自ImageView。
<TextView
android:id="@+id/nextBtn"
android:layout_width="250dp"
android:layout_height="80dp"
android:background="@drawable/bg_0062ec_40"
android:gravity="center"
android:text="下一步"
android:textColor="#FFFFFF"
android:textSize="34sp" />
<ImageView
android:id="@+id/backBtn"
android:layout_width="100dp"
android:layout_height="100dp"
android:scaleType="center"
app:srcCompat="@drawable/icon_back" />
转载自:Android中TextView与Button的区别
Button继承于TextView,一般情况下,TextView用来承载静态文本,Button用来响应点击事件。但是TextView 继承自View,点击事件是从View就有的特性,所以TextView也能点击。那么TextView与Button有什么不同呢?
1.TextView中文字默认是从左上方开始,Button中文字默认是居中显示
2.TextView默认背景透明,Button默认背景灰色的
3.TextView点击无效果,Button默认状态下点击变黄色(它有一个默认的背景选择器)
4.TextView默认不拦截点击事件,Button会拦截点击事件(比如说我们一个ListView,Item的布局中有一个TextView和Button,我们在这个TextView上点击会触发ListView的OnItemClickListener方法,在Button上点击并不会触发ListView的OnItemClickListener方法,因为Button把这个点击事件拦截了)。
节选自:Android Context完全解析,你所不知道的Context的各种细节
Context一共有三种类型,分别是Application、Activity和Service。
Context数量 = Activity数量 + Service数量 + 1
上面的1代表着Application的数量,因为一个应用程序中可以有多个Activity和多个Service,但是只能有一个Application。
Application单例模式:
public class MyApplication extends Application {
private static MyApplication app;
public static MyApplication getInstance() {
return app;
}
@Override
public void onCreate() {
super.onCreate();
app = this;
}
}
见类 io.grpc.stub.MetadataUtils,其中有个方法:
/**
* Attaches a set of request headers to a stub.
*
* @param stub to bind the headers to.
* @param extraHeaders the headers to be passed by each call on the returned stub.
* @return an implementation of the stub with {@code extraHeaders} bound to each call.
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1789")
public static <T extends AbstractStub<T>> T attachHeaders(
T stub,
final Metadata extraHeaders) {
return stub.withInterceptors(newAttachHeadersInterceptor(extraHeaders));
}
稍微自己封装一下的效果,如下:
private static <T extends AbstractStub<T>> T attachHeaders(T stub, final Map<String, String> headerMap) {
Metadata extraHeaders = new Metadata();
if (headerMap != null) {
for (String key : headerMap.keySet()) {
Metadata.Key<String> customHeadKey = Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER);
extraHeaders.put(customHeadKey, headerMap.get(key));
}
}
return MetadataUtils.attachHeaders(stub, extraHeaders);
}
添加依赖
// Glide implementation 'com.github.bumptech.glide:glide:4.11.0' implementation 'com.github.bumptech.glide:okhttp3-integration:4.11.0'
然后就可以了,添加 OkHttp 集成库的 Gradle 依赖将使 Glide 自动开始使用 OkHttp 来加载所有来自 http 和 https URL 的图片。
参考链接:
1.Hello
syntax = "proto3";
option java_multiple_files = true;
package hello;
service Hello {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
2.gRPCService
import hello.HelloGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
public class gRPCService {
private static final String gRPC_HOST = "isilent.me";
private static final int gRPC_PORT = 80;
private static gRPCService instance;
private ManagedChannel mChannel;
public static gRPCService getInstance() {
if (instance == null) {
instance = new gRPCService();
}
return instance;
}
private gRPCService() {
}
/**
* 获取Channel
*
* @return
*/
private ManagedChannel getChannel() {
if (mChannel == null || mChannel.isShutdown()) {
// 设置最大接收消息大小为20M
mChannel = ManagedChannelBuilder.forAddress(gRPC_HOST, gRPC_PORT).usePlaintext().maxInboundMessageSize(20 * 1024 * 1024).build();
}
return mChannel;
}
/**
* 获取Hello存根
*
* @return
*/
public HelloGrpc.HelloStub getHelloStub() {
return HelloGrpc.newStub(getChannel());
}
}
3.SimpleStreamObserver
import android.os.Handler;
import android.os.Looper;
import io.grpc.stub.StreamObserver;
public abstract class SimpleStreamObserver<T> implements StreamObserver<T> {
private static Handler handler = new Handler(Looper.getMainLooper());
@Override
public void onCompleted() {
}
@Override
public void onNext(final T value) {
// 返回主线程
handler.post(new Runnable() {
@Override
public void run() {
onSuccess(value);
}
});
}
/**
* 请求成功的回调
*
* @param value
*/
protected abstract void onSuccess(T value);
}
4.Main
public static void Main() {
HelloRequest request = HelloRequest.newBuilder().setName("hello").build();
gRPCService.getInstance().getHelloStub().sayHello(request, new SimpleStreamObserver<HelloReply>() {
@Override
protected void onSuccess(HelloReply value) {
System.out.println(value.getMessage());
}
@Override
public void onError(Throwable t) {
}
});
}
JAVA使用的是一种名为值传递的求值策略,这种策略在传值过程中会复制实参的引用,并将这份拷贝传入到方法形参中,所以对形参的任何重赋值操作都不会对实参产生影响。
参考链接:
1.下载安装Protobuf Support插件,如图所示:
2.在项目根目录的 build.gradle 的 buildscript 中加入 protobuf-gradle-plugin 插件:
buildscript {
...
dependencies {
...
classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.12"
}
}
3.在应用Module的 build.gradle 中进行如下配置
apply plugin: 'com.android.application'
apply plugin: 'com.google.protobuf'
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.11.0' }
plugins {
grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.29.0' }
}
generateProtoTasks {
all().each { task ->
task.builtins {
java { option 'lite' }
}
task.plugins {
grpc { option 'lite' }
}
}
}
}
dependencies {
// gRPC
implementation 'io.grpc:grpc-okhttp:1.29.0'
implementation 'io.grpc:grpc-protobuf-lite:1.29.0'
implementation 'io.grpc:grpc-stub:1.29.0'
implementation 'javax.annotation:javax.annotation-api:1.2'
}
4.最后将 .proto 协议文件放在 src/main/proto/ 文件夹下,点击build进行编译,如果出现如下图,则证明环境配置成功!
参考链接: