update stackoverflow, 2023-06-10 00:02:03
Some checks are pending
Deploy GitHub Page / docs-deploy (push) Waiting to run

This commit is contained in:
yzqdev 2023-06-10 00:02:03 +08:00
commit 07761ea08a
6 changed files with 595 additions and 628 deletions

View file

@ -59,3 +59,566 @@ val menuHost = requireActivity()
})
```
# 视图绑定
在gradle文件中开启ViewBinding功能后,编译器就会为此模块下的每个布局文件都产生一个对应的绑定类。
这个绑定类是我们的布局名称去掉下划线使用驼峰的形式结尾接Binding
例如:
activity_gender_guide.xml
就是:
ActivityGenderGuideBinding
使用viewbinding后不需要再findViewById找控件
直接通过binding.控件Id名称就可以控件id名称也是去掉下滑线使用驼峰的形式。
viewbinding的inflate有两种方法根据直接所需选择
1inflate(getLayoutInflater());
2inflate(inflater, container, false);
## 在activity使用
```java
public class GenderGuideActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//之前的写法
setContentView(R.layout.activity_gender_guide);
TextView guide_title = (TextView) findViewById(R.id.guide_title);
guide_title.setText("标题");
//使用viewbinding的写法
ActivityGenderGuideBinding binding = ActivityGenderGuideBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.guideTitle.setText("标题");
}
}
// viewbindng用法
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding=ActivityMainBinding.inflate(layoutInflater)
setContentView(R.layout.activity_main)
}
}
```
### 带有include
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_money_income);
ActivityMoneyIncomeBinding moneyIncomeBinding = ActivityMoneyIncomeBinding.bind(getContainer());;
//如果include的布局是当前 module里的布局
//就可以直接调用
//moneyIncomeBinding.moneyView.title.setText("标题");
//如果是其它module里的
//那么需要在哪个module里开启viewbinding
//调用方法
View money_view = findViewById(R.id.money_view);
MartianMoneyWithdrawViewBinding moneyBinding = MartianMoneyWithdrawViewBinding.bind(money_view);
moneyBinding.title.setText("标题");
}
```
```kotlin
class MainFragment : Fragment() {
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentMainBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
```
## fragment使用
```java
public class ReadingHistoryFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//以前的写法
View view = inflater.inflate(R.layout.list_with_empty_view, null);
TextView empty_text = (TextView) view.findViewById(R.id.empty_text);
empty_text.setText("标题");
return view;
//使用viewbinding的写法
ListWithEmptyViewBinding binding = ListWithEmptyViewBinding.inflate(inflater, container, false);
binding.emptyText.setText("标题");
return binding.getRoot();
}
}
```
## BaseAdapter使用
以前的写法
```java
public class ListAdapter extends BaseAdapter {
private Activity activity;
private List<String> list;
public ListAdapter(Activity activity, List<String> list) {
this.activity = activity;
this.list = list;
}
@Override
public int getCount() {
return list == null ? 0 : list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
class ViewHolder {
ImageView iv_cover;
TextView tv_bookname;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(activity).inflate(R.layout.archive_list_item, null);
holder = new ViewHolder();
holder.iv_cover = (ImageView) convertView.findViewById(R.id.iv_cover);
holder.tv_bookname = (TextView) convertView.findViewById(R.id.tv_bookname);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
}
```
viewbinding写法
```java
public class ListAdapter extends BaseAdapter {
private Activity activity;
private List<String> list;
public ListAdapter(Activity activity, List<String> list) {
this.activity = activity;
this.list = list;
}
@Override
public int getCount() {
return list == null ? 0 : list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ArchiveListItemBinding binding;
if (convertView == null) {
binding = ArchiveListItemBinding.inflate(activity.getLayoutInflater(), null, false);
convertView = binding.getRoot();
convertView.setTag(binding);
} else {
binding = (ArchiveListItemBinding) convertView.getTag();
}
binding.tvBookname.setText("标题");
return convertView;
}
}
```
kotlin
```kt
private inner class MyAdapter : BaseAdapter() {
override fun getCount(): Int {
return projects.size
}
override fun getItem(position: Int): Project {
return projects[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view: View
val binding = ViewcoreItemListBinding.inflate(
LayoutInflater.from(requireContext()),
null,
false
)
if (convertView == null) {
val project = getItem(position)
binding.title.text = project.title
binding.desc.text = project.desc
return binding.root
} else {
view = convertView
}
return view
}
}
```
## 在RecyclerView结合Adapter使用
```java
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> {
private List<String> mList;
public MainAdapter(List<String> list) {
mList = list;
}
@NonNull
@Override
public MainAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//之前的写法
//View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_comment_item, parent, false);
//ViewHolder holder = new ViewHolder(view);
//使用ViewBinding的写法
LayoutCommentItemBinding commentItemBinding = LayoutCommentItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
ViewHolder holder = new ViewHolder(commentBinding);
return holder;
}
@Override
public void onBindViewHolder(@NonNull MainAdapter.ViewHolder holder, int position) {
holder.mTextView.setText("标题");
}
@Override
public int getItemCount() {
return mList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView mTextView;
//之前的写法
//public ViewHolder(@NonNull View itemView) {
// super(itemView);
// mTextView = itemView.findViewById(R.id.tv_name);
//}
//使用ViewBinding的写法
ViewHolder(@NonNull LayoutCommentItemBinding commentItemBinding) {
super(commentItemBinding.getRoot());
mTextView = commentItemBinding.tvName;
}
}
}
```
kotlin
```kotlin
class FruitAdapter(val fruitList: List<Fruit>) : RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
inner class ViewHolder(binding: FruitItemBinding) : RecyclerView.ViewHolder(binding.root) {
val fruitImage: ImageView = binding.fruitImage
val fruitName: TextView = binding.fruitName
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = FruitItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val fruit = fruitList[position]
holder.fruitImage.setImageResource(fruit.imageId)
holder.fruitName.text = fruit.name
}
override fun getItemCount() = fruitList.size
```
## 自定义dialog使用
```java
public static void showRechargeAlertDialog(Context context, String title, int type, final OnSingleChoiceSelectedListener singleChoiceSelectedListener){
//之前的写法
View view = View.inflate(context, R.layout.dialog_recharge, null);
TextView dialog_title = view.findViewById(R.id.dialog_title);
dialog_title.setText("标题");
final AlertDialog alertDialog = createAlertDialog(context, view, true);
//使用viewbinding的写法
DialogRechargeBinding binding = DialogRechargeBinding.inflate(LayoutInflater.from(context));
binding.dialogTitle.setText("标题");
final AlertDialog alertDialog = createAlertDialog(context, binding.getRoot(), true);
}
//创建共用的dialog的属性
public static AlertDialog createAlertDialog(Context context, View view, boolean isCancelable){
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setView(view);
final AlertDialog catDialog = builder.show();
catDialog.setCancelable(isCancelable);//按返回键是否可以退出true允许
catDialog.getWindow().setBackgroundDrawable(null);
catDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
WindowManager.LayoutParams lp = catDialog.getWindow().getAttributes();
lp.width = SystemUtil.getScreenWidth(context); //设置宽度
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
catDialog.getWindow().setAttributes(lp);
return catDialog;
}
```
例子
```kotin
package kim.hsl.vb;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import kim.hsl.vb.databinding.DialogBinding;
public class ViewBindingDialog extends Dialog {
public ViewBindingDialog(@NonNull Context context) {
super(context);
}
public ViewBindingDialog(@NonNull Context context, int themeResId) {
super(context, themeResId);
}
protected ViewBindingDialog(@NonNull Context context, boolean cancelable,
@Nullable OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 1 . 获取视图绑定类
DialogBinding binding = DialogBinding.inflate(getLayoutInflater());
// 2 . 设置对话框布局
setContentView(binding.getRoot());
// 3 . 通过视图绑定类访问布局中的视图组件
binding.textView.setText("视图绑定对话框示例 \nDialogBinding");
// 4 . 设置对话框大小 ( 仅做参考 美观处理 与主题无关 )
WindowManager.LayoutParams params = getWindow().getAttributes();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = 400;
getWindow().setAttributes(params);
}
}
```
:::tip
在布局文件中使用viewBinding
include标签的viewBinding使用
:::
MainActivity
```xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="@+id/titleBar"
layout="@layout/titlebar" />
...
</LinearLayout>
```
下面是插入的布局
一定要记得给include的布局加上id属性不然到MainActivity中就找不到了
```xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="Back" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Title"
android:textSize="20sp" />
<Button
android:id="@+id/done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="Done" />
</RelativeLayout>
```
kotlin代码
```kotlin
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.titleBar.title.text = "Title"
binding.titleBar.back.setOnClickListener {
}
binding.titleBar.done.setOnClickListener {
}
}
}
```
## merge标签的viewBinding使用
使用merge标签时假设我们引入的布局文件如下
```xml
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="Back" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Title"
android:textSize="20sp" />
<Button
android:id="@+id/done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="Done" />
</merge>
```
与include不同的是在引入时去掉id属性防止崩溃
```xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
layout="@layout/titlebar" />
</LinearLayout>
```
kotlin代码
```kotlin
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var titlebarBinding: TitlebarBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
titlebarBinding = TitlebarBinding.bind(binding.root)
setContentView(binding.root)
titlebarBinding.title.text = "Title"
titlebarBinding.back.setOnClickListener {
}
titlebarBinding.done.setOnClickListener {
}
}
}
```

View file

@ -1,13 +1,21 @@
# gradle配置
# 安卓相关
## 安卓使用libs
```
```groovy
implementation fileTree(include: ['*.jar',"*.aar"], dir: 'libs')
```
使用kts
```kotlin
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar", "*.aar"))))
implementation(fileTree("libs") {
include("*.jar", "*.aar")
})
```
## 安卓权限
<https://www.jianshu.com/p/892a2ca5c41e>
@ -92,7 +100,6 @@ Apply Changes按钮在菜单栏上在运行的右侧新增两个按钮
adb shell getprop ro.product.name
```
## 升级gradlew
gradle init 脚本

View file

@ -1,562 +0,0 @@
# 视图绑定
在gradle文件中开启ViewBinding功能后,编译器就会为此模块下的每个布局文件都产生一个对应的绑定类。
这个绑定类是我们的布局名称去掉下划线使用驼峰的形式结尾接Binding
例如:
activity_gender_guide.xml
就是:
ActivityGenderGuideBinding
使用viewbinding后不需要再findViewById找控件
直接通过binding.控件Id名称就可以控件id名称也是去掉下滑线使用驼峰的形式。
viewbinding的inflate有两种方法根据直接所需选择
1inflate(getLayoutInflater());
2inflate(inflater, container, false);
## 在activity使用
```java
public class GenderGuideActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//之前的写法
setContentView(R.layout.activity_gender_guide);
TextView guide_title = (TextView) findViewById(R.id.guide_title);
guide_title.setText("标题");
//使用viewbinding的写法
ActivityGenderGuideBinding binding = ActivityGenderGuideBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.guideTitle.setText("标题");
}
}
// viewbindng用法
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding=ActivityMainBinding.inflate(layoutInflater)
setContentView(R.layout.activity_main)
}
}
```
### 带有include
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_money_income);
ActivityMoneyIncomeBinding moneyIncomeBinding = ActivityMoneyIncomeBinding.bind(getContainer());;
//如果include的布局是当前 module里的布局
//就可以直接调用
//moneyIncomeBinding.moneyView.title.setText("标题");
//如果是其它module里的
//那么需要在哪个module里开启viewbinding
//调用方法
View money_view = findViewById(R.id.money_view);
MartianMoneyWithdrawViewBinding moneyBinding = MartianMoneyWithdrawViewBinding.bind(money_view);
moneyBinding.title.setText("标题");
}
```
```kotlin
class MainFragment : Fragment() {
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentMainBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
```
## fragment使用
```java
public class ReadingHistoryFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//以前的写法
View view = inflater.inflate(R.layout.list_with_empty_view, null);
TextView empty_text = (TextView) view.findViewById(R.id.empty_text);
empty_text.setText("标题");
return view;
//使用viewbinding的写法
ListWithEmptyViewBinding binding = ListWithEmptyViewBinding.inflate(inflater, container, false);
binding.emptyText.setText("标题");
return binding.getRoot();
}
}
```
## BaseAdapter使用
以前的写法
```java
public class ListAdapter extends BaseAdapter {
private Activity activity;
private List<String> list;
public ListAdapter(Activity activity, List<String> list) {
this.activity = activity;
this.list = list;
}
@Override
public int getCount() {
return list == null ? 0 : list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
class ViewHolder {
ImageView iv_cover;
TextView tv_bookname;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(activity).inflate(R.layout.archive_list_item, null);
holder = new ViewHolder();
holder.iv_cover = (ImageView) convertView.findViewById(R.id.iv_cover);
holder.tv_bookname = (TextView) convertView.findViewById(R.id.tv_bookname);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
}
```
viewbinding写法
```java
public class ListAdapter extends BaseAdapter {
private Activity activity;
private List<String> list;
public ListAdapter(Activity activity, List<String> list) {
this.activity = activity;
this.list = list;
}
@Override
public int getCount() {
return list == null ? 0 : list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ArchiveListItemBinding binding;
if (convertView == null) {
binding = ArchiveListItemBinding.inflate(activity.getLayoutInflater(), null, false);
convertView = binding.getRoot();
convertView.setTag(binding);
} else {
binding = (ArchiveListItemBinding) convertView.getTag();
}
binding.tvBookname.setText("标题");
return convertView;
}
}
```
kotlin
```kt
private inner class MyAdapter : BaseAdapter() {
override fun getCount(): Int {
return projects.size
}
override fun getItem(position: Int): Project {
return projects[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view: View
val binding = ViewcoreItemListBinding.inflate(
LayoutInflater.from(requireContext()),
null,
false
)
if (convertView == null) {
val project = getItem(position)
binding.title.text = project.title
binding.desc.text = project.desc
return binding.root
} else {
view = convertView
}
return view
}
}
```
## 在RecyclerView结合Adapter使用
```java
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> {
private List<String> mList;
public MainAdapter(List<String> list) {
mList = list;
}
@NonNull
@Override
public MainAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//之前的写法
//View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_comment_item, parent, false);
//ViewHolder holder = new ViewHolder(view);
//使用ViewBinding的写法
LayoutCommentItemBinding commentItemBinding = LayoutCommentItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
ViewHolder holder = new ViewHolder(commentBinding);
return holder;
}
@Override
public void onBindViewHolder(@NonNull MainAdapter.ViewHolder holder, int position) {
holder.mTextView.setText("标题");
}
@Override
public int getItemCount() {
return mList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView mTextView;
//之前的写法
//public ViewHolder(@NonNull View itemView) {
// super(itemView);
// mTextView = itemView.findViewById(R.id.tv_name);
//}
//使用ViewBinding的写法
ViewHolder(@NonNull LayoutCommentItemBinding commentItemBinding) {
super(commentItemBinding.getRoot());
mTextView = commentItemBinding.tvName;
}
}
}
```
kotlin
```kotlin
class FruitAdapter(val fruitList: List<Fruit>) : RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
inner class ViewHolder(binding: FruitItemBinding) : RecyclerView.ViewHolder(binding.root) {
val fruitImage: ImageView = binding.fruitImage
val fruitName: TextView = binding.fruitName
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = FruitItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val fruit = fruitList[position]
holder.fruitImage.setImageResource(fruit.imageId)
holder.fruitName.text = fruit.name
}
override fun getItemCount() = fruitList.size
```
## 自定义dialog使用
```java
public static void showRechargeAlertDialog(Context context, String title, int type, final OnSingleChoiceSelectedListener singleChoiceSelectedListener){
//之前的写法
View view = View.inflate(context, R.layout.dialog_recharge, null);
TextView dialog_title = view.findViewById(R.id.dialog_title);
dialog_title.setText("标题");
final AlertDialog alertDialog = createAlertDialog(context, view, true);
//使用viewbinding的写法
DialogRechargeBinding binding = DialogRechargeBinding.inflate(LayoutInflater.from(context));
binding.dialogTitle.setText("标题");
final AlertDialog alertDialog = createAlertDialog(context, binding.getRoot(), true);
}
//创建共用的dialog的属性
public static AlertDialog createAlertDialog(Context context, View view, boolean isCancelable){
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setView(view);
final AlertDialog catDialog = builder.show();
catDialog.setCancelable(isCancelable);//按返回键是否可以退出true允许
catDialog.getWindow().setBackgroundDrawable(null);
catDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
WindowManager.LayoutParams lp = catDialog.getWindow().getAttributes();
lp.width = SystemUtil.getScreenWidth(context); //设置宽度
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
catDialog.getWindow().setAttributes(lp);
return catDialog;
}
```
例子
```kotin
package kim.hsl.vb;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import kim.hsl.vb.databinding.DialogBinding;
public class ViewBindingDialog extends Dialog {
public ViewBindingDialog(@NonNull Context context) {
super(context);
}
public ViewBindingDialog(@NonNull Context context, int themeResId) {
super(context, themeResId);
}
protected ViewBindingDialog(@NonNull Context context, boolean cancelable,
@Nullable OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 1 . 获取视图绑定类
DialogBinding binding = DialogBinding.inflate(getLayoutInflater());
// 2 . 设置对话框布局
setContentView(binding.getRoot());
// 3 . 通过视图绑定类访问布局中的视图组件
binding.textView.setText("视图绑定对话框示例 \nDialogBinding");
// 4 . 设置对话框大小 ( 仅做参考 美观处理 与主题无关 )
WindowManager.LayoutParams params = getWindow().getAttributes();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = 400;
getWindow().setAttributes(params);
}
}
```
:::tip
在布局文件中使用viewBinding
include标签的viewBinding使用
:::
MainActivity
```xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="@+id/titleBar"
layout="@layout/titlebar" />
...
</LinearLayout>
```
下面是插入的布局
一定要记得给include的布局加上id属性不然到MainActivity中就找不到了
```xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="Back" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Title"
android:textSize="20sp" />
<Button
android:id="@+id/done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="Done" />
</RelativeLayout>
```
kotlin代码
```kotlin
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.titleBar.title.text = "Title"
binding.titleBar.back.setOnClickListener {
}
binding.titleBar.done.setOnClickListener {
}
}
}
```
## merge标签的viewBinding使用
使用merge标签时假设我们引入的布局文件如下
```xml
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="Back" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Title"
android:textSize="20sp" />
<Button
android:id="@+id/done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="Done" />
</merge>
```
与include不同的是在引入时去掉id属性防止崩溃
```xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
layout="@layout/titlebar" />
</LinearLayout>
```
kotlin代码
```kotlin
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var titlebarBinding: TitlebarBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
titlebarBinding = TitlebarBinding.bind(binding.root)
setContentView(binding.root)
titlebarBinding.title.text = "Title"
titlebarBinding.back.setOnClickListener {
}
titlebarBinding.done.setOnClickListener {
}
}
}
```

View file

@ -1,8 +1,8 @@
# HashMap遍历 #
# HashMap遍历
在Java中有多种遍历HashMap的方法。让我们回顾一下最常见的方法和它们各自的优缺点。由于所有的Map都实现了Map接口所以接下来方法适用于所有MapHaspMapTreeMap,LinkedMap,HashTable,etc
## 方法#1 使用For-Each迭代entries ##
## 方法1 使用For-Each迭代entries ##
这是最常见的方法并在大多数情况下更可取的。当你在循环中需要使用Map的键和值时就可以使用这个方法
@ -15,7 +15,7 @@
注意For-Each循环是Java5新引入的所以只能在Java5以上的版本中使用。如果你遍历的map是null的话For-Each循环会抛出NullPointerException异常所以在遍历之前你应该判断是否为空引用。
## 方法#2 使用For-Each迭代keys和values ##
## 方法2 使用For-Each迭代keys和values ##
如果你只需要用到map的keys或values时你可以遍历KeySet或者values代替entrySet
@ -39,7 +39,7 @@
使用泛型
```
```java
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
@ -49,7 +49,7 @@
```
不使用泛型
```java
Map map = new HashMap();
Iterator entries = map.entrySet().iterator();
while (entries.hasNext()) {
@ -58,24 +58,24 @@
Integer value = (Integer)entry.getValue();
System.out.println("Key = " + key + ", Value = " + value);
}
```
你可以使用同样的技术迭代keyset或者values
这个似乎有点多余但它具有自己的优势。首先它是遍历老java版本map的唯一方法。另外一个重要的特性是可以让你在迭代的时候从map中删除entries的(通过调用iterator.remover())唯一方法.如果你试图在For-Each迭代的时候删除entries你将会得到unpredictable resultes 异常。
从性能方法看这个方法等价于使用For-Each迭代
## 方法#4 迭代keys并搜索values低效的 ##
## 方法4 迭代keys并搜索values低效的 ##
```java
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Integer key : map.keySet()) {
Integer value = map.get(key);
System.out.println("Key = " + key + ", Value = " + value);
}
```
这个方法看上去比方法#1更简洁但是实际上它更慢更低效通过key得到value值更耗时这个方法在所有实现map接口的map中比方法#1慢20%-200%。如果你安装了FindBugs它将检测并警告你这是一个低效的迭代。这个方法应该避免
## 总结 ##
## 总结
如果你只需要使用key或者value使用方法#2如果你坚持使用java的老版本java 5 以前的版本或者打算在迭代的时候移除entries使用方法#3。其他情况请使用#1方法。避免使用#4方法

View file

@ -1,41 +0,0 @@
# 如何在classpath中设置多个jar包
### 问题
是否有一个方法可以在classpath选项中包含一个文件夹目录下的所有jar包
我尝试运行`java -classpath lib/*.jar:. my.package.Program`但是无法找到相应的类文件可是这些类文件确实存在于命令中的jar包中。我是否需要在classpath中分别指定所有的jar包
### 回答
在使用Java6或者以上版本时classpath选项可以支持通配符(wildcards)。使用方法如下:
* 使用直接引用(`"`)
* 使用 `*` 而不是 `*.jar`
**Windows平台**
`java -cp "Test.jar;lib/*" my.package.MainClass`
**Unix平台**
`java -cp "Test.jar:lib/*" my.package.MainClass`
Unix平台与Windows平台基本一样除了使用冒号 `:` 替代分号 `;` 之外。如果你不能使用通配符,也可以使用`bash`完成上述功能命令如下其中lib是一个包含所有jar包的目录
`java -cp $(echo lib/*.jar | tr ' ' ':')`
注意事项classpath选项与-jar选项并不能兼容。可以查看[Execute jar file with multiple classpath libraries from command prompt](http://stackoverflow.com/questions/13018100/execute-jar-file-with-multiple-classpath-libraries-from-command-prompt)
**对于通配符的理解**
来自[Classpath](http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html)文档:
类路径可以包含一个基本文件名通配符`*`,其等价于指定一个特定目录下的所有以.jar或.JAR为后缀的文件的列表。例如一个类路径的条目为`foo/*`其指定了foo目录下的所有jar文件。一个仅仅包含`*`的classpath条目(entry)指定了当前目录下的所有jar包。
一个包含了`*`的classpath条目不能匹配特定目录下的class文件。为了既能匹配foo目录下的类文件也能匹配jar包可以使用`foo;foo/*``foo/*;foo`。对于前者而言类文件和资源选择的顺序先是foo目录下的类文件和资源之后才是jar包而后者则正好相反。
通配符并不能递归地搜索子目录下的jar包。例如`foo/*`只找`foo`目录下的jar包而不会寻找`foo/bar``foo/baz`等目录下的jar包。
一个目录中的jar包枚举顺序并不固定这不仅和平台有关甚至可能会在同一个机器上因为时间不同而表现不同。一个结构良好well-constructed的应用不应该依赖于某个特定的顺序。如果特定顺序是不可避免的时候就需要在classpath中显示枚举所有的jar包了。
在类加载进程中通配符的扩展在早期完成优先于程序main函数的调用而不是在其后。每个包含通配符的类路径都被替换为所在目录下所有jar包的序列。例如如果目录`foo`包含`a.jar``b.jar`以及`c.jar`,因此类路径`foo/*`被扩展为`foo/a.jar;foo/b.jar;foo/c.jar`,并且以上字符串被作为系统属性`java.class.path`的值。
环境变量`CLASSPATH`与命令行选项-classpath或者-cp并没有什么不同。也就是说通配符既可以应用于命令行`-classpath/-cp`选项中,也可以应用于环境变量`CLASSPATH`中。
stackoverflow原地址<http://stackoverflow.com/questions/219585/setting-multiple-jars-in-java-classpath>

View file

@ -15,19 +15,19 @@
"highlight.js": "11.8.0"
},
"devDependencies": {
"@vuepress/cli": "2.0.0-beta.62",
"@vuepress/client": "2.0.0-beta.62",
"@vuepress/plugin-docsearch": "2.0.0-beta.62",
"@vuepress/plugin-prismjs": "2.0.0-beta.62",
"@vuepress/utils": "2.0.0-beta.62",
"@vuepress/cli": "2.0.0-beta.63",
"@vuepress/client": "2.0.0-beta.63",
"@vuepress/plugin-docsearch": "2.0.0-beta.63",
"@vuepress/plugin-prismjs": "2.0.0-beta.63",
"@vuepress/utils": "2.0.0-beta.63",
"@vueuse/core": "10.1.2",
"sass": "1.62.1",
"sass": "1.63.2",
"sass-loader": "13.3.1",
"vue": "3.3.4",
"vuepress": "2.0.0-beta.62",
"vuepress-shared": "2.0.0-beta.221",
"vuepress-theme-hope": "2.0.0-beta.221",
"vuepress-vite": "2.0.0-beta.62",
"vuepress-webpack": "2.0.0-beta.62"
"vuepress": "2.0.0-beta.63",
"vuepress-shared": "2.0.0-beta.224",
"vuepress-theme-hope": "2.0.0-beta.224",
"vuepress-vite": "2.0.0-beta.63",
"vuepress-webpack": "2.0.0-beta.63"
}
}