update stackoverflow, 2023-06-10 00:02:03
Some checks are pending
Deploy GitHub Page / docs-deploy (push) Waiting to run
Some checks are pending
Deploy GitHub Page / docs-deploy (push) Waiting to run
This commit is contained in:
parent
7dfd7af7f3
commit
07761ea08a
6 changed files with 595 additions and 628 deletions
|
|
@ -59,3 +59,566 @@ val menuHost = requireActivity()
|
|||
})
|
||||
|
||||
```
|
||||
|
||||
# 视图绑定
|
||||
|
||||
在gradle文件中开启ViewBinding功能后,编译器就会为此模块下的每个布局文件都产生一个对应的绑定类。
|
||||
这个绑定类是我们的布局名称去掉下划线使用驼峰的形式结尾接Binding;
|
||||
例如:
|
||||
activity_gender_guide.xml
|
||||
就是:
|
||||
ActivityGenderGuideBinding
|
||||
|
||||
使用viewbinding后,不需要再findViewById找控件,
|
||||
直接通过binding.控件Id名称就可以,控件id名称也是去掉下滑线使用驼峰的形式。
|
||||
viewbinding的inflate有两种方法,根据直接所需选择
|
||||
1:inflate(getLayoutInflater());
|
||||
2:inflate(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 {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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 脚本
|
||||
|
|
|
|||
|
|
@ -1,562 +0,0 @@
|
|||
# 视图绑定
|
||||
|
||||
在gradle文件中开启ViewBinding功能后,编译器就会为此模块下的每个布局文件都产生一个对应的绑定类。
|
||||
这个绑定类是我们的布局名称去掉下划线使用驼峰的形式结尾接Binding;
|
||||
例如:
|
||||
activity_gender_guide.xml
|
||||
就是:
|
||||
ActivityGenderGuideBinding
|
||||
|
||||
使用viewbinding后,不需要再findViewById找控件,
|
||||
直接通过binding.控件Id名称就可以,控件id名称也是去掉下滑线使用驼峰的形式。
|
||||
viewbinding的inflate有两种方法,根据直接所需选择
|
||||
1:inflate(getLayoutInflater());
|
||||
2:inflate(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 {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
# HashMap遍历 #
|
||||
# HashMap遍历
|
||||
|
||||
在Java中有多种遍历HashMap的方法。让我们回顾一下最常见的方法和它们各自的优缺点。由于所有的Map都实现了Map接口,所以接下来方法适用于所有Map(如:HaspMap,TreeMap,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方法。
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
22
package.json
22
package.json
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue