android开发可用技巧

都是本人在android开发的学习过程中用到的小技巧,记录于此,便于以后查找

获取屏幕尺寸

DisplayMetrics dm = getResources().getDisplayMetrics();
int screenWidth = dm.widthPixels;
int screenHeight = dm.heightPixels;

自定义view获取自身尺寸

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);float width = getMeasuredWidth();float height = getMeasuredHeight();
}

dp和px转换

//dp转px
final float scale = context.getResources().getDisplayMetrics().density;
pxValue = (int) (dpValue * scale + 0.5f);
//px转dp
final float scale = context.getResources().getDisplayMetrics().density;
dpValue = (int) (pxValue / scale + 0.5f);

获取状态栏高度

public int getStatusBarHeight() {Resources resources = Resources.getSystem();int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");return resources.getDimensionPixelSize(resourceId);
}

设置状态栏字体颜色

//isLightModel为true字体黑,反之字体白
public static void setStatusBarLightMode(Activity activity, boolean isLightMode) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {Window window = activity.getWindow();int option = window.getDecorView().getSystemUiVisibility();if (isLightMode) {option |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;} else {option &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;}window.getDecorView().setSystemUiVisibility(option);}
}

状态栏透明

//方法一:不兼容低版本
//res/values/styles.xml(改AppTheme的方式)
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"><item name="android:windowTranslucentStatus">false</item><item name="android:windowTranslucentNavigation">true</item><item name="android:statusBarColor">@android:color/transparent</item>
</style>
//方法二:兼容低版本
public void makeStatusBarTransparent(Activity activity) {if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {return;}Window window = activity.getWindow();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);int option = window.getDecorView().getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;window.getDecorView().setSystemUiVisibility(option);window.setStatusBarColor(Color.TRANSPARENT);} else {window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);}
}
//再结合隐藏标题栏即可

按返回键

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {//业务逻辑return true;}return super.onKeyDown(keyCode, event);
}

字体不跟随系统设置

@Override
public Resources getResources() {Resources res=super.getResources();Configuration config=new Configuration();config.setToDefaults();res.updateConfiguration(config,res.getDisplayMetrics());return res;
}

去除标题栏

ActionBar actionBar = getSupportActionBar();
if(actionBar != null){actionBar.hide();
}

广播监听网络状态

//需要的uses-permission:
android.permission.INTERNET
android.permission.ACCESS_NETWORK_STATE
//onResume中:
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(netStateReceiver,filter);
//定义广播接收器
BroadcastReceiver netStateReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if(action.equals(ConnectivityManager.CONNECTIVITY_ACTION)){//此时网络状态发生变化->调用获取网络状态的方法获取网络状态即可}}
};

获取当前网络状态

//需要的uses-permission:
android.permission.INTERNET
android.permission.ACCESS_NETWORK_STATE
int getNetWorkStatus(Context context){ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();if (activeNetworkInfo!=null&&activeNetworkInfo.isConnected()){if (activeNetworkInfo.getType()==(ConnectivityManager.TYPE_WIFI)){return NETWORK_WIFI;}else if (activeNetworkInfo.getType()==(ConnectivityManager.TYPE_MOBILE)){return NETWORK_MOBILE;}}else {return NETWORK_NONE;}return NETWORK_NONE;
}

收起软键盘

private void hideKeyboard(){View view = getCurrentFocus();if(view != null){InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);}
}

数据存储到手机本地

SharedPreferences.Editor editor = getSharedPreferences("文件名",MODE_PRIVATE).edit();
editor.putString("key",value);
editor.apply();

读取手机本地存储的数据

SharedPreferences pref = getSharedPreferences("文件名",MODE_PRIVATE);
String username = pref.getString("key","默认值");

跳转至浏览器打开网站

Uri uri = Uri.parse("http://www.xxx.cn/");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

正则判断手机号格式是否正确

private boolean isPhone(String phone) {String regex = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$";if (phone.length() != 11) {return false;} else {Pattern p = Pattern.compile(regex);Matcher m = p.matcher(phone);return m.matches();}
}

长按控件

控件.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()){case MotionEvent.ACTION_DOWN://单指按下break;case MotionEvent.ACTION_UP://单指释放break;case MotionEvent.ACTION_MOVE://移动break;case MotionEvent.ACTION_CANCEL://取消break;case MotionEvent.ACTION_POINTER_DOWN://多指按下break;case MotionEvent.ACTION_POINTER_UP://多指释放break;}return false;}
});

更新app

//动态注册广播接收器
private void initReceiver(){IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);registerReceiver(downloadApkReceiver,filter);
}
//下载更新包
private void downloadApk(){DownloadManager.Request request = new DownloadManager.Request(Uri.parse("下载地址"));request.setDestinationInExternalFilesDir(this,Environment.DIRECTORY_DOWNLOADS,"xxx.apk");request.setTitle("xxx.apk");request.setDescription("xxx");request.setVisibleInDownloadsUi(true);DownloadManager apkDownloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);long mReference = apkDownloadManager.enqueue(request);
}
//定义下载完成时的广播接收器
BroadcastReceiver downloadApkReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if(action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)){//下载完成,提交handler处理}}
};
//handler中
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){boolean canInstallApk = getPackageManager().canRequestPackageInstalls();if(!canInstallApk){//向用户拿安装apk的权限Uri uri = Uri.parse("package:"+getPackageName());Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,uri);startActivityForResult(intent,996);}else{installApk("storage/emulated/0/Android/data/com.example.xxx/files/Download/xxx.apk");}
}else{installApk("storage/emulated/0/Android/data/com.example.xxx/files/Download/xxx.apk");
}
//拿到权限后安装
@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data){super.onActivityResult(requestCode,resultCode,data);if(requestCode == 996){installApk("storage/emulated/0/Android/data/com.example.xxx/files/Download/xxx.apk");}
}
//安装更新包
private void installApk(String downloadApk) {StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();StrictMode.setVmPolicy(builder.build());builder.detectFileUriExposure();Uri uri = Uri.fromFile(new File(downloadApk));Intent installIntent = new Intent(Intent.ACTION_VIEW);installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);installIntent.setDataAndType(uri, "application/vnd.android.package-archive");startActivity(installIntent);
}

界面不被软键盘挤上去

//activity配置xml中
android:windowSoftInputMode:adjustPan

获取系统当前时间(自定义时间格式)

SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date curDate = new Date(System.currentTimeMillis());
String nowTime = timeFormat.format(curDate);

设置透明

//方法一
xml中 android:alpha 设置0到1
//方法二
xml中 android:background 设置#xx红绿蓝 xx为16进制
//方法三
view.getBackground().setAlpha(x); 设置0到255

监听软键盘点击完成

xml中 EditText
android:singleLine true
android:imeOptions="某action"
java中
EditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {@Overridepublic boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {if(i == EditorInfo.IME_ACTION_SEARCH){//业务逻辑return true;}return false;}
});
imeOptions可选值分别是:
actionDone 完成 EditorInfo.IME_ACTION_DONE
actionGo 前进 EditorInfo.IME_ACTION_GO
actionPrevious 上一项 EditorInfo.IME_ACTION_PREVIOUS
actionNext 下一项 EditorInfo.IME_ACTION_NEXT
actionSearch 搜索 EditorInfo.IME_ACTION_SEARCH
actionSend 发送 EditorInfo.IME_ACTION_SEND
actionUnspecified 未指定 EditorInfo.IME_ACTION_UNSPECIFIED
actionNone 无动作 EditorInfo.IME_ACTION_NONE

延时处理延迟处理

new Handler().postDelayed(new Runnable() {@Overridepublic void run() {//业务逻辑}
},延迟的时间毫秒);

数据库SQLite

//先创建一个数据库类
public class DBHelper extends SQLiteOpenHelper {private static Integer Version = 1;public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version){super(context, name, factory, version);}public DBHelper(Context context, String name, int version){this(context,name,null,version);}public DBHelper(Context context,String name){this(context, name, Version);}@Overridepublic void onCreate(SQLiteDatabase db) {String sql = "create table record(id integer primary key autoincrement,content text,time varchar(60))";db.execSQL(sql);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
}
//java中使用
DBHelper dbHelper = new DBHelper(context,"record");
SQLiteDatabase db = dbHelper.getWritableDatabase();
//增
ContentValues values = new ContentValues();
values.put("content",content);
values.put("time",time);
db.insert("record",null,values);
//删
db.delete("record","id=?",new String[]{id});
//改
ContentValues values = new ContentValues();
values.put("content",content);
values.put("time",time;
db.update("record",values,"id=?",new String[]{id});
//查
Cursor cursor = db.query("record", new String[]{"id","content","time"}, "content LIKE ? ",new String[]{"%"+keywords+"%"},null,null,"time DESC");
while (cursor.moveToNext()) {String id = cursor.getString(cursor.getColumnIndex("id"));String content = cursor.getString(cursor.getColumnIndex("content"));String time = cursor.getString(cursor.getColumnIndex("time"));//业务逻辑
}
//关闭数据库
db.close();

shape

corners //圆角属性
android:radius //数值
android:topLeftRadius //数值
android:topRightRadius //数值
android:bottomLeftRadius //数值
android:bottomRightRadius //数值gradient //渐变属性
android:angle //渐变角度,必须为45的倍数,0为从左到右,90为从上到下
android:startColor //渐变开始点的颜色
android:endColor //渐变结束点的颜色
android:centerColor //渐变中间点的颜色
android:centerX //渐变中心X的相当位置,范围为0~1
android:centerY //渐变中心Y的相当位置,范围为0~1
android:type=["linear" | "radial" | "sweep"] //渐变类型,线性渐变(默认)/放射渐变/扫描式渐变
android:gradientRadius= //渐变的半径,只有当渐变类型为radial时才能使用
android:useLevel=["true" | "false"] //使用LevelListDrawable时就要设置为true。设为false时才有渐变效果padding //边距属性
android:left //数值
android:top //数值
android:right //数值
android:bottom //数值solid //填充属性
android:color //颜色stroke //描边属性
android:width //宽度
android:color //颜色
android:dashWidth //虚线的宽度,值为0时是实线
android:dashGap //虚线的间隔size //大小属性
android:width //数值
android:height //数值

selector

//注:用于设置background时用android:drawable,用于设置各种color时用android:color
item android:state_pressed="false"
android:drawable(或color)//未被按住时的样子
item android:state_pressed="true"
android:drawable(或color) //被按住时的样子
类似的还有:
//设置是否选中状态,true表示已选中,false表示未选中
android:state_selected
//设置是否勾选状态,主要用于CheckBox和RadioButton,true表示已被勾选,false表示未被勾选
android:state_checked
//设置勾选是否可用状态,类似state_enabled,只是state_enabled会影响触摸或点击事件,state_checkable影响勾选事件
android:state_checkable
//设置是否获得焦点状态,true表示获得焦点,默认为false,表示未获得焦点
android:state_focused
//设置触摸或点击事件是否可用状态,一般只在false时设置该属性,表示不可用状态
android:state_enabled

message带数据提交handler

//message:
Message message = new Message();
message.what = 1;
Bundle bundle = new Bundle();
bundle.putString("key",value);
message.setData(bundle);
handler.sendMessage(message);
//handler中:
String value = message.getData().getString("key");

数据转json

//简单的键值对数组
JSONObject jsonObject = new JSONObject();
jsonObject.put("key1","value1");
jsonObject.put("key2","value2");
String json = jsonObject.toString();
//稍复杂的多维数组,子元素为自定义类,且子元素没键名
需要引入gson:implementation 'com.google.code.gson:gson:2.7'
List<自定义类> list = new ArrayList<>();
list.add(new 自定义类(xxx));
list.add(new 自定义类(xxx));
Gson gson = new Gson();
String json = gson.toJson(list);
//更复杂的多维数组,子元素为自定义类,且子元素有键名
需要引入gson:implementation 'com.google.code.gson:gson:2.7'
Map map = new HashMap<>();
map.put("key1",new 自定义类(xxx));
map.put("key2",new 自定义类(xxx));
String json = gson.toJson(map);

解析json

//JSONObject方式解析(灵活方便,能满足绝大多数情况)
try{JSONObject jsonObject = new JSONObject("json字符串");String code = jsonObject.getString("code");                     JSONObject result = jsonObject.getJSONObject("result");JSONArray data = result.getJSONArray("data");for (int i = 0;i < data.length();i++){JSONObject value = data.getJSONObject(i);String title = value.getString("title");}
}catch(Exception e){e.printStackTrace();
}
//gson方式解析(需要自定义类,麻烦,适用情况:自定义类存在)
需要引入gson:implementation 'com.google.code.gson:gson:2.7'
Gson gson = new Gson();
List<自定义类> list = new ArrayList<>();
list = gson.fromJson("json字符串",new TypeToken>(){}.getType());

bitmap转base64

public String bitmapToBase64(Bitmap bitmap){String result = null;ByteArrayOutputStream byteArrayOutputStream = null;try{if(bitmap != null){byteArrayOutputStream = new ByteArrayOutputStream();bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);byteArrayOutputStream.flush();byteArrayOutputStream.close();byte[] bitmapBytes = byteArrayOutputStream.toByteArray();result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);}}catch(IOException e){e.printStackTrace();}finally{try{if(byteArrayOutputStream != null){byteArrayOutputStream.flush();byteArrayOutputStream.close();}}catch(IOException e){e.printStackTrace();}}return result;
}

图片处理(缩放尺寸、改变质量、旋转)

//缩放图片大小
Matrix matrix = new Matrix();
matrix.setScale(0.1f, 0.1f);
Bitmap saveBitmap = Bitmap.createBitmap(originBitmap,0,0,originBitmap.getWidth(),originBitmap.getHeight(),matrix,true);
//降低图片质量
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int quality = 50;//图片质量,0-100,值越小质量越差
originBitmap.compress(Bitmap.CompressFormat.JPEG,quality,byteArrayOutputStream);
Bitmap saveBitmap = BitmapFactory.decodeStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()),null,null);
//旋转图片
int width = originBitmap.getWidth();
int height = originBitmap.getHeight();
Matrix matrix = new Matrix();
matrix.setRotate(angle);//angle为旋转的角度
Bitmap saveBitmap = Bitmap.createBitmap(originBitmap, 0, 0, width, height, matrix, false);

okhttp3发送get请求

//需要引入okhttp3:implementation 'com.squareup.okhttp3:okhttp:3.4.1'
Thread thread = new Thread(){public void run(){OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url(url).build();try{Response response = client.newCall(request).execute();String result = response.body().string();//业务逻辑(若要更新UI需提交给handler处理)}catch(Exception e){e.printStackTrace();}}
};
thread.start();

okhttp3发送post请求

//需要引入okhttp3:implementation 'com.squareup.okhttp3:okhttp:3.4.1'
Thread thread = new Thread(){public void run(){OkHttpClient client = new OkHttpClient();RequestBody requestBody = new FormBody.Builder().add("key",value).build();Request request = new Request.Builder().url(url).post(requestBody).build();try{Response response = client.newCall(request).execute();String result = response.body().string();//业务逻辑(若要更新UI需提交给handler处理)}catch(Exception e){e.printStackTrace();}}
};
thread.start();

okhttp3发送json格式的post请求

//需要引入okhttp3:implementation 'com.squareup.okhttp3:okhttp:3.4.1'
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
Thread thread = new Thread(){@Overridepublic void run(){String json = "自己组织json";OkHttpClient okHttpClient = new OkHttpClient();RequestBody requestBody = RequestBody.create(JSON,json);Request request = new Request.Builder().url(url).post(requestBody).build();try{Response response=okHttpClient.newCall(request).execute();String result = response.body().string();//业务逻辑(若要更新UI需提交给handler处理)}catch(Exception e){e.printStackTrace();}}
};
thread.start();

动态设置文字样式

设置字体大小:
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX,getResources().getDimensionPixelSize(R.dimen.xxx));
//如果设置后字体过大,用:
textView.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX,getResources().getDimension(R.dimen.xx));
设置字体颜色:
textView.setTextColor(getResources().getColor(R.color.xxx));
设置样式:
textView.setTypeface(Typeface.SANS_SERIF,Typeface.NORMAL);
Typeface.BOLD //粗体
Typeface.BOLD_ITALIC //粗斜体
Typeface.ITALIC //斜体
Typeface.NORMAL //常规

时间选择器

private TimePickerView pvTime;
//需要显示时间的控件点击显示选择器
textView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {pvTime.show(textView);}
});
//设置选择器
Calendar selectedDate = Calendar.getInstance();//默认选中时间
Calendar startDate = Calendar.getInstance();
startDate.set(2018, 12, 1);//可选时间范围的初始时间
Calendar endDate = Calendar.getInstance();
endDate.set(2029, 12, 31);//可选时间范围的结束时间
pvTime = new TimePickerView.Builder(this, new TimePickerView.OnTimeSelectListener() {@Overridepublic void onTimeSelect(Date date, View v) {TextView btn = (TextView) v;btn.setText(getTimes(date));//getTimes为自定义函数,目的是把date转成需要的时间格式}
}).setType(new boolean[]{true, true, true, false, false, false})//显示选项年月日时分秒
.setLabel("年", "月", "日", "时", "", "")//显示格式
.isCenterLabel(true)
.setDividerColor(Color.DKGRAY)
.setContentSize(21)
.setDate(selectedDate)
.setRangDate(startDate, endDate)
.setDecorView(null)
.build();

时间选择器-年月日

Calendar c = Calendar.getInstance();
new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() {@Overridepublic void onDateSet(DatePicker datePicker, int i, int i1, int i2) {String date = i + "年" + (i1+1) + "月" + i2 + "日";}
},c.get(Calendar.YEAR),c.get(Calendar.MONTH),c.get(Calendar.DAY_OF_MONTH)).show();

时间选择器-时分

Calendar c = Calendar.getInstance();
new TimePickerDialog(this, new TimePickerDialog.OnTimeSetListener() {@Overridepublic void onTimeSet(TimePicker timePicker, int i, int i1) {String time = i + "点" + i1 + "分";}
},c.get(Calendar.HOUR_OF_DAY),c.get(Calendar.MINUTE),true).show();

保留两位小数

private String keep2decimal(float f){DecimalFormat df = new DecimalFormat("#.00");return df.format(f);
}

ListView(子元素为一条文本)

活动布局xml中加控件:ListView
String[] data = {"","","","",""};
ArrayAdapter adapter = new ArrayAdapter(XXActivity.this,android.R.layout.simple_list_item_1,data);
ListView list = (ListView)findViewById(R.id.list);
list.setAdapter(adapter);
//点击获取子元素的值
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView parent, View view, int position, long id) {String string = ((TextView)view).getText().toString();}
});

recyclerView

需要引入:implementation 'com.android.support:recyclerview-v7:28.0.0'
活动布局xml中加控件:RecyclerView
布局xml中加子元素布局;
新建adapter:
public class XXAdapter extends RecyclerView.Adapter{private List<XX> list;private Context context;public XXAdapter(List<XX> list, Context context){this.list = list;this.context = context;}@Overridepublic int getItemCount(){//根据获取到的list显示希望显示的子元素个数return list.size();}@Overridepublic int getItemViewType(int position){//position为list的角标,根据业务逻辑返回不同的值return 1;}class AHolder extends RecyclerView.ViewHolder{private View aView;public AHolder(View itemView){super(itemView);aView = itemView;}}class BHolder extends RecyclerView.ViewHolder{private TextView bTV;public BHolder(View itemView){super(itemView);bTV = (TextView)itemView.findViewById(R.id.b);}}@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){//根据getItemViewType返回的值返回不同的holderif(viewType == 1){return new AHolder(LayoutInflater.from(context).inflate(R.layout.a_item,null));}else{return new BHolder(LayoutInflater.from(context).inflate(R.layout.b_item,null));}}//点击子元素监听的接口public interface OnItemClickListener {void onClick(XX xx);}private OnItemClickListener listener;public void setOnItemClickListener(OnItemClickListener listener) {this.listener = listener;}@Overridepublic void onBindViewHolder(final RecyclerView.ViewHolder holder,final int position){if(holder instanceof AHolder){((AHolder) holder).aView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (listener != null) {listener.onClick(list.get(position));}}});}else{XX xx = list.get(position);((BHolder) holder).bTV.setText(xx.getB());}}
}
activity中:
private RecyclerView recyclerView;
private GridLayoutManager mLayoutManager;
private XXAdapter adapter;
recyclerView = (RecyclerView)findViewById(R.id.recyclerView);
adapter = new XXAdapter(list,MainActivity.this);
mLayoutManager = new GridLayoutManager(MainActivity.this,1);//数字表示显示的列数
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setAdapter(adapter);
recyclerView.setItemAnimator(new DefaultItemAnimator());//默认动画样式,可自定义
//子项的点击事件处理
adapter.setOnItemClickListener(new XXAdapter.OnItemClickListener() {@Overridepublic void onClick(XX xx) {}
});

ImageView加载网络图片

需要引入:implementation 'com.github.bumptech.glide:glide:4.0.0'
布局xml中加入ImageView
Glide.with(context).load(url).into(imageView);

加载gif

需要引入:implementation 'com.github.bumptech.glide:glide:4.0.0'
布局xml中加入ImageView
Glide.with(context).load(url).asGif().diskCacheStrategy(DiskCacheStrategy.SOURCE).into(imageView);
//加上diskCacheStrategy的目的是为了加载更快
DiskCacheStrategy.NONE 什么都不缓存
DiskCacheStrategy.SOURCE 仅仅只缓存原来的全分辨率的图像
DiskCacheStrategy.RESULT 仅仅缓存最终的图像,即降低分辨率后的(或者是转换后的)
DiskCacheStrategy.ALL 缓存所有版本的图像(默认行为)

自定义控件组合

创建布局文件my_layout.xml,比如最外侧控件为LinearLayout,含一个TextView
创建java文件:
public class MyLayout extends LinearLayout {public MyLayout(Context context,AttributeSet attributeSet){super(context,attributeSet);LayoutInflater.from(context).inflate(R.layout.my_layout,this);//findViewById获取控件,并可添加事件监听}
}
xml中:直接使用MyLayout控件
java中:layout.addView(myLayout);

加载摄像头并拍照

/需要权限:android.permission.CAMERA
布局xml中:TextureView
activity中:
需要:implements TextureView.SurfaceTextureListener
定义:
private TextureView cameraView;
private Camera mCamera;
业务逻辑:
cameraView = (TextureView)findViewById(R.id.cameraView);
cameraView.setSurfaceTextureListener(MainActivity.this);
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {// 打开相机 0后置 1前置mCamera = Camera.open(0);if (mCamera != null) {try {mCamera.setDisplayOrientation(90);// 设置预览角度,并不改变获取到的原始数据方向// 绑定相机和预览的ViewmCamera.setPreviewTexture(surface);} catch (IOException e) {e.printStackTrace();}}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {mCamera.stopPreview();mCamera.setPreviewCallback(null);mCamera.release();return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
//某行为触发开启摄像头预览
mCamera.startPreview();
mCamera.autoFocus(null);
//某行为触发拍照(拍单张)
mCamera.takePicture(null,null,new Camera.PictureCallback(){@Overridepublic void onPictureTaken(byte[] data,Camera camera){Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length);//业务逻辑(图片可能角度不对,需要旋转)releaseCamera();}
});
//某行为触发拍照(拍多张)
mCamera.setPreviewCallback(new Camera.PreviewCallback(){@Overridepublic void onPreviewFrame(byte[] data,Camera camera){//以下可以用和上面单张一样的处理方式,也可以用下面的处理方式Camera.Size size = camera.getParameters().getPreviewSize();try{YuvImage image = new YuvImage(data,ImageFormat.NV21,size.width,size.height,null);if(image!=null){ByteArrayOutputStream stream = new ByteArrayOutputStream();image.compressToJpeg(new Rect(0,0,size.width,size.height),80,stream);Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(),0,stream.size());//业务逻辑stream.close();}}catch(Exception e){e.printStackTrace();}}
});

dialog:两个按钮

AlertDialog.Builder builder = new AlertDialog.Builder(this).setIcon(R.mipmap.图标).setTitle("标题").setMessage("内容")
.setPositiveButton("确定(积极)", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {//}
}).setNegativeButton("取消(消极)", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {//}
});
builder.create().show();

dialog:三个按钮

AlertDialog.Builder builder = new AlertDialog.Builder(this).setIcon(R.mipmap.图标).setTitle("标题").setMessage("内容")
.setPositiveButton("确定(积极)", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {//}
}).setNeutralButton("不选(中立)", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {//}
}).setNegativeButton("取消(消极)", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {//}
});
builder.create().show();

dialog:列表

final String[] items = {"item 1", "item 2", "item 3", "item 4", "item 5", "item 6"};
AlertDialog.Builder builder = new AlertDialog.Builder(this).setIcon(R.mipmap.图标)
.setTitle("标题")
.setItems(items, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {//(i为当前点击的项所在items脚标)}
});
builder.create().show();

dialog:多选

final String[] items = {"多选1", "多选2", "多选3", "多选4", "多选5", "多选6"};
boolean[] isSelect = {false, false, false, false, false, false};//默认选中状态
AlertDialog.Builder builder = new AlertDialog.Builder(this).setIcon(R.mipmap.图标)
.setTitle("标题")
.setMultiChoiceItems(items, isSelect, new DialogInterface.OnMultiChoiceClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i, boolean b) {//(i为当前点击的项所在items脚标,b为点击后是否为选中状态)}
}).setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {//选择时用数组记录选中的项,这里确定时循环数组处理业务}
});
builder.create().show();

dialog:单选

final String[] items = {"单选1", "单选2", "单选3", "单选4", "单选5", "单选6"};
AlertDialog.Builder builder = new AlertDialog.Builder(this).setIcon(R.mipmap.图标).setTitle("标题")
.setSingleChoiceItems(items, 默认选中脚标, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {//(i为当前点击的项所在items脚标)}
}).setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {//}
});
builder.create().show();

dialog:圆圈加载

ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setIcon(R.mipmap.图标);
progressDialog.setTitle("标题");
progressDialog.setMessage("内容...");
//是否形成一个加载动画,true表示不明确加载进度形成转圈动画,false表示明确
progressDialog.setIndeterminate(true);
//点击返回键或者dialog四周是否关闭dialog
progressDialog.setCancelable(false);
progressDialog.show();
//加载完成后关闭dialog
progressDialog.dismiss();

dialog:进度条加载

final int MAX_VALUE = 100;
ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setIcon(R.mipmap.图标);
progressDialog.setProgress(0);
progressDialog.setTitle("标题");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMax(MAX_VALUE);
progressDialog.show();
new Thread(new Runnable() {@Overridepublic void run() {int progress = 0;while (progress < MAX_VALUE) {try {Thread.sleep(100);progress++;progressDialog.setProgress(progress);} catch (InterruptedException e) {e.printStackTrace();}}//加载完毕自动关闭dialogprogressDialog.cancel();}
}).start();

dialog:自定义

第一种:纯自定义
View dialogView = View.inflate(this, R.layout.自定义布局, null);
dialogView.findViewById(R.id.xx).控件处理
AlertDialog.Builder builder = new AlertDialog.Builder(this).setView(dialogView);
AlertDialog alertDialog = builder.create();
alertDialog.show();
//完成后关闭dialog
alertDialog.dismiss();第二种:只有中间部分是自定义,仍有标题按钮等
View dialogView = LayoutInflater.from(this).inflate(R.layout.自定义布局, null);
xx = dialogView.findViewById(R.id.xx);
AlertDialog.Builder builder = new AlertDialog.Builder(this).setView(dialogView)
.setIcon(R.mipmap.图标).setTitle("标题")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {@Override
public void onClick(DialogInterface dialogInterface, int i) {//根据xx控件的值处理
}
});
builder.create().show();第三种:view是java创建的控件
final EditText editText = new EditText(this);
其他和第二种一样,只是把editText作为setView()的参数

单选框

xml中:
一个RadioGroup下放入多个RadioButton
activity中:
设置默认选中项:
radioButton.setChecked(true);
选中事件监听:
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup radioGroup, int i) {RadioButton radioButton = (RadioButton)findViewById(radioGroup.getCheckedRadioButtonId());String type = radioButton.getText().toString();//}
});

多选框

xml中:
多个CheckBox
activity中:
设置默认选中项:
checkBox.setChecked(true);
选中事件监听:
activity implements CompoundButton.OnCheckedChangeListener
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {//(b为点击后是否为选中状态)
//(compoundButton为选中的CheckBox,可用getText().toString()获取值)
}

下拉框

xml中:
一个Spinner
activity中:
Spinner spinner = (Spinner) findViewById(R.id.spinner);
final String[] items = new String[]{"item1", "item2", "item3", "item4", "item5"};
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setSelection(2);//默认选中项脚标
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {@Overridepublic void onItemSelected(AdapterView adapterView, View view, int i, long l) {//(i为当前点击的项所在items脚标)//view可以转换为TextView,然后设置字体样式}@Overridepublic void onNothingSelected(AdapterView adapterView) {}
});

canvas

Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
Paint.Style.STROKE:只画边框
Paint.Style.FILL:只填充内部
Paint.Style.FILL_AND_STROKE:既画边框又填充内部
paint.setAntiAlias(true);//开启抗锯齿
paint.setColor(Color.parseColor("#FF83FA"));
paint.setStrokeWidth(20);
//设置能画渐变背景的paint
SweepGradient mSweepGradient = new SweepGradient(渐变中心x,渐变中心y,new int[]{颜色、颜色。。。},null);
paint.setShader(mSweepGradient);
//画点
canvas.drawPoint(x, y, paint);
//画线
canvas.drawLine(startX, startY, stopX, stopY, paint);
//画矩形
canvas.drawRect(left, top, right, bottom, paint);
//画圆角矩形
canvas.drawRoundRect(left, top, right, bottom, paint, x轴半径, y轴半径, paint);
//画椭圆
canvas.drawOval(left, top, right, bottom, paint);
//画圆
canvas.drawCircle(圆心x, 圆心y, 半径, paint);
//画圆弧
canvas.drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
startAngle:圆弧开始的角度
sweepAngle:圆弧扫描的角度
useCenter:是否将中心点与圆弧连起来形成扇形
//画图片
canvas.drawBitmap(bitmap, left, top, paint);
//画文字
paint.setTextSize(100);
canvas.drawText("文字",文字左侧离左边缘距离,文字下面离上边缘距离,paint);
//如果需要文字居中
paint.setTextAlign(Paint.Align.CENTER);
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float distance = (fontMetrics.bottom - fontMetrics.top)/2 - fontMetrics.bottom;
canvas.drawText(currentStageName,父级中心x,父级中心y+distance,paint);

自定义view

//values下创建attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="MyView"><attr name="text" format="string" /><attr name="size" format="integer" /></declare-styleable>
</resources>
//MyView类
public class MyView extends View {public MyView(Context context, AttributeSet attrs){super(context, attrs);TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyView);String text = ta.getString(R.styleable.MyView_text);int size = ta.getInteger(R.styleable.MyView_size, 100);ta.recycle();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//canvas.drawC。。。}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);//尺寸相关操作}
}
//布局中放入MyView
app:text="测试text属性"
app:size="200"

从手机相册获取图片

需要权限:android:name="android.permission.READ_EXTERNAL_STORAGE"
打开相册:
Intent intent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RESULT_LOAD_IMAGE);
获取图片:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data) {Uri selectedImage = data.getData();String[] filePathColumn = {MediaStore.Images.Media.DATA};Cursor cursor = getContentResolver().query(selectedImage,filePathColumn,null,null,null);cursor.moveToFirst();int columnIndex = cursor.getColumnIndex(filePathColumn[0]);String picturePath = cursor.getString(columnIndex);Bitmap bitmap = getBitmapFromLocalImage(picturePath);//cursor.close();}
}
从图片地址获取bitmap:
private Bitmap getBitmapFromLocalImage(String path){Bitmap bitmap = null;try {BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));bitmap = BitmapFactory.decodeStream(bis);bis.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return bitmap;
}

动态获取权限

private void requestPermission(){String permissions[] = {Manifest.permission.READ_EXTERNAL_STORAGE,//...};ArrayList toApplyList = new ArrayList();for(String perm : permissions){if(PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this,perm)){toApplyList.add(perm);}}String tmpList[] = new String[toApplyList.size()];if(!toApplyList.isEmpty()){ActivityCompat.requestPermissions(this,toApplyList.toArray(tmpList),123);}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode,permissions,grantResults);if (requestCode == 123) {for (int i = 0; i < permissions.length; i++) {if (grantResults[i] == PERMISSION_GRANTED) {Toast.makeText(this, "" + "权限" + permissions[i] + "申请成功", Toast.LENGTH_SHORT).show();} else {Toast.makeText(this, "" + "权限" + permissions[i] + "申请失败", Toast.LENGTH_SHORT).show();}}}
}

TextView加载html代码

import static android.text.Html.FROM_HTML_MODE_LEGACY;
textView.setText(Html.fromHtml("HTML代码",FROM_HTML_MODE_LEGACY));

动态改变控件尺寸

ViewGroup.LayoutParams lp = view.getLayoutParams();
lp.width = 宽度;
lp.height = 高度;
view.setLayoutParams(lp);

减数定时器

private CountDownTimer cdt = new CountDownTimer(总执行时间, 每次执行时间间隔) {@Overridepublic void onTick(long millisUntilFinished) {//业务逻辑}@Overridepublic void onFinish() {cdt.cancel();}
};
cdt.start();

定时器

Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {@Overridepublic void run() {//业务逻辑}
};
timer.schedule(timerTask,延迟的毫秒数,定时执行的毫秒数);
if(timer != null){timer.cancel();
}

ImageView旋转

静态旋转:
xml设置rotation="度数"
动态旋转:
imageView.setPivotX(imageView.getWidth()/2);
imageView.setPivotY(imageView.getHeight()/2);//支点在图片中心
imageView.setRotation("度数");

EditText内容改变监听

editText.addTextChangedListener(new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}@Overridepublic void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}@Overridepublic void afterTextChanged(Editable editable) {//业务逻辑//将光标移动到末尾//editText.setSelection(editText.getText().length());}
});

EditText焦点变化监听

editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {@Overridepublic void onFocusChange(View v, boolean hasFocus) {//业务逻辑(hasFocus表示是否获得焦点)}
});

循环父布局中的子元素

for (int i = 0;i < linearLayout.getChildCount(); i++){if (linearLayout.getChildAt(i) instanceof TextView) {TextView textView = (TextView)linearLayout.getChildAt(i);//业务逻辑}
}

彩色阴影

需要引入:implementation 'com.lijiankun24:shadowlayout:1.0.0'
布局xml中:
xmlns:app="http://schemas.android.com/apk/res-auto"
com.lijiankun24.shadowlayout.ShadowLayout
属性:
app:shadowColor="#66000000" 控制阴影的颜色,注意:颜色必须带有透明度的值
app:shadowDx="0dp" 控制阴影 x 轴的偏移量
app:shadowDy="3dp" 控制阴影 y 轴的偏移量
app:shadowRadius="10dp" 控制阴影的范围
app:shadowSide="all|left|right|top|bottom" 控制阴影显示的边界,共有五个值

setText设置拼接字符串

values-strings.xml中:
例:text:字符串%1$s整数%2$d小数%3$f%n$s--->n表示目前是第几个参数 (比如%1$s中的1代表第一个参数),s代表字符串%n$d--->n表示目前是第几个参数 (比如%2$d中的2代表第二个参数),d代表整数%n$f--->n表示目前是第几个参数 (比如%3$f中的3代表第三个参数),f代表浮点数
textView.setText(String.format(getResources().getString(R.string.text),String,int,float));

ScrollView滑到底部或顶部

scrollView.post(new Runnable() {@Overridepublic void run() {//滑到底部scrollView.fullScroll(View.FOCUS_DOWN);//滑到顶部scrollView.fullScroll(View.FOCUS_UP);}
});

手机振动震动

权限:uses-permission android:name="android.permission.VIBRATE"
初始化:Vibrator vibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE);
判断是否有振动器:vibrator.hasVibrator()
短振动:vibrator.vibrate(1000); // 振动1秒
节奏振动:vibrator.vibrate(new long[]{500, 1000, 500, 2000}, -1);
// 暂停500毫秒,振动1秒,暂停500毫秒,振动2秒
// 第二个参数为-1则振动一遍,第二个参数为0则重复振动
暂停振动:vibrator.cancel();

屏幕保持常亮

方法一:直接在xml顶层布局中:
android:keepScreenOn="true"方法二:java中设置:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

从其它线程访问主线程更新UI

方法一:
Activity.runOnUiThread(new Runnable() {@Overridepublic void run() {//更新UI}
});
方法二:
View.post(new Runnable() {@Overridepublic void run() {//更新UI}
});
方法三:
view.postDelayed(new Runnable() {@Overridepublic void run() {//更新UI}
}, 延迟的毫秒数);
方法四:
Handler

android开发可用技巧相关推荐

  1. Android开发小技巧 | 一句命令搞定截屏

    -- 简书作者 谢恩铭 转载请注明出处 一句命令搞定截屏 在安卓开发中, 我们很多时候都要用到截屏这个功能. 有时是为了演示, 有时是为了报告问题(比如在Bugzilla, Jira, Redmine ...

  2. Android 开发小技巧 | 一句命令搞定截屏

    -- 作者 谢恩铭 转载请注明出处 一句命令搞定截屏 在安卓开发中, 我们很多时候都要用到截屏这个功能. 有时是为了演示, 有时是为了报告问题(比如在Bugzilla, Jira, Redmine等B ...

  3. android开发小技巧:实现listview异步加载图片

    2019独角兽企业重金招聘Python工程师标准>>> 针对listview异步加载图片这个问题,麦子学院android开发老师讲了一种非常实用的方法,麦子学院android开发老师 ...

  4. Android 开发小技巧(2)

    转自:农民伯伯: http://www.cnblogs.com/over140/ 常用代码 7.1   在当前Activity中启动另外一个Activity startActivity(new Int ...

  5. Android开发-小技巧汇总2

    启动虚拟机时,在 launch options 窗口中 有个 wipe user data ,勾选它,将会让虚拟机 [恢复出厂设置] 2.[如果想让自己的应用程序有多个启动图标:] 为一个应用的 多个 ...

  6. Android开发——小技巧:推荐辅助工具(icon图标网站、在线取色网站以及视频学习网站)

    图标网站: Iconfont-阿里巴巴矢量图标库 https://www.iconfont.cn/home/index?spm=a313x.7781069.1998910419.2 在线取色网站: R ...

  7. android开发 常用技巧

    1> 通用布局  android:orientation="horizontal"/"vertical"(睡直) android:layout_width ...

  8. Android开发实用技巧之一:全局获取Context的技巧

    以下为up主阅读郭大神<第一行代码>后整理的笔记: 我们都知道活动本身就是一个Context对象,但是,当应用程序构架复杂起来的时候,很多的逻辑代码都会脱离Activity类, 而很多时候 ...

  9. Android开发帮助技巧(适用于入门)(第一部分-高效地构建项目的准备工作和Activity与Fragment的交互介绍)

    平台: windows11 Android Studio 4.2.2 Build #AI-202.7660.26.42.7486908, built on June 24, 2021 Runtime ...

最新文章

  1. 一个 Blink 小白的成长之路
  2. 经典模式流水灯实验的个人总结和思考
  3. Python module模块 包 __name__
  4. 哪个app最费电_关于石墨烯养生地暖,业主最关心的几大问题,答案附上!
  5. java rpm包安装_rpm包安装java jar开机自启
  6. 模板---使用el选项指定模板/使用template选项指定内联模板/使用template选项指定独立模板/使用render选项指定要挂载的模板
  7. 有了它,从此走上炫酷的编码之路!
  8. python post请求参数化,参数化包含JSON主体的python POST请求
  9. matlab size11,matlab学习笔记11_3高维数组操作 filp, shiftdim, size, permute, ipermute
  10. 视频教程-通俗易懂的JavaScript高级教程(含资料)-JavaScript
  11. OSCS开源软件安全周报,一分钟了解本周开源软件安全大事
  12. cad2010多个文件并排显示_CAD软件同时显示两张或多张图纸的方法
  13. H264/AVC协议基本概况
  14. ue怎么转换html格式,UE编辑器UltraEdit怎么格式化代码
  15. python读取excel汉字转成拼音_python实现汉字转拼音和读写excel
  16. 微信域名防封、域名检测接口api、域名跳转技术、360防拦截揭秘(二)------传统防封的弊端
  17. web3调用智能合约取事件
  18. 计算机选择固态硬盘,好马配好鞍,电脑是选固态硬盘还是机械硬盘?
  19. 计算机软件资格入户,考信息系统项目管理师证书是不是可以申请入户
  20. 2021-09-18 Stage/Job cancelled because SparkContext was shut down

热门文章

  1. 【RT-Thread】nxp rt10xx SFUD和FAL组件搭建与使用
  2. rsvp.exe,AdskScSrv.exe ,avp.exe
  3. Linux下poky编译1
  4. NVT 66X增加WIFI命令
  5. jQuery 经典表单应用
  6. Java语言每日一练—第14天:银行收入计算
  7. 企业必备的13种体系认证大盘点!
  8. 今天,辛辛苦苦开发的雷超站终于上线了
  9. 【tutorabc多少钱一节课】上完课的我来说说真实感想
  10. 【分布式】一致性哈希和哈希槽