疯狂安卓入门,crayandroid
系列文章目录
文章目录
- 系列文章目录
- 第一组 ViewGroup 为基类
- 帧布局
- 约束布局
- 第二组 TextView 及其子类
- button
- 时钟 AnalogClock 和 TextClock
- 计时器
- 第三组 ImageView 及其子类
- 第四组 AdapterView 及其子类
- AutoCompleteTextView 的功能和用法
- ExapndaleListView
- AdapterViewFlipper
- RecyclerView 组件
- 第五组UI ProgressBar及其子类
- SeekBar
- RatingBar
- 第六组 ViewAnimator
- 第七组UI对话框
- android事件机制
- 基于监听的事件处理
- 基于回调的事件处理
- 响应系统设置
- Configuration类
- 3.5 Handler消息传递机制
- 3.5.1 Handler 类
- 3.5.2 Handler, Loop, MessageQueue的工作原理
- 4 Activity & Fragment
- 包含多个Activity的Manifest
- Activity的启动和关闭
- 使用Bundle在Activity之间交换数据
- 4.3 Activity生命周期
- 4. android:launchMode=
- 4.4.1 standard 模式 (默认模式)
- 4.4.2 singleTop 模式
- 4.4.3 singleTask 模式
- 4.4.4 singleInstance 模式
- 4.5 Fragment
- 4.5.3 Fragment与Activity通讯
- 4.5.4 Fragment管理与Fragment事务
- chapter 5 Intent, IntentFilter
- 5.1 Intent对象
- 5.2 Intent属性及 intent-filter 配置
- Compoent 属性
- Action, Category属性
- Data, Type 属性
- 实例:使用Action, Data属性启动系统Activity
- Extra 属性
- Flag 属性
- 6 Android 应用资源
- 6.1 应用资源
- 5.2 定义字符串 颜色 尺寸资源文件 数组
- 6.4 Drawable资源
- 6.4.2 StateListDrawable资源
- 6.4.3 LayerDrawable 资源
- 6.4.6 ShapeDrawable资源
- 6.4.5 ClipDrawable 资源
- 6.4.6 AnimationDrawable资源
- 6.5 属性动画资源 Property Animation
- 6.6 使用原始XML资源; Layout资源; Menu资源
- 6.9 样式和主题 style theme
- 6.10 属性资源
- 6.11 使用原始资源
- 6.12 国际化资源
- 6.13 适应不同屏幕的资源
- xxx
- 9 使用ContentProvider实现数据共享
- 10 Service和BroadcastReceiver
- 10.1 Service
- 10.1.5 IntentService
- 10.2 跨进程调用 Service(AIDL Service)
- 14 管理Android系统桌面
- 14.1 动态壁纸 Live Wallpapers
- xml
- java
第一组 ViewGroup 为基类
ViewGroup继承自View类
View <- ViewGroup <- LinearLayout <- TableLayout
向TableLayout中添加 TableRow (容器) 就是插入了一行
帧布局
ViewGroup <- FrameLayout
public class MainActivity extends AppCompatActivity {int [] names = new int[] {R.id.view01, R.id.view02, R.id.view03, R.id.view04, R.id.view05, R.id.view06};TextView[] views = new TextView[names.length];class MyHandler extends Handler {private WeakReference<MainActivity> activity;public MyHandler(WeakReference<MainActivity> activity) {this.activity = activity;}private int currentColor = 0;int[] colors = new int[]{R.color.red,R.color.green,R.color.blue,R.color.yellow,R.color.pink,R.color.teal};@Overridepublic void handleMessage(@NonNull Message msg) {if (msg.what == 0x123) {for (int i = 0, len = activity.get().names.length; i < len; i++) {activity.get().views[i].setBackgroundResource(colors[(i + currentColor) % colors.length]);}++currentColor;}super.handleMessage(msg);Log.d("thid", "handleMessage:" + Thread.currentThread().getId());}}private Handler handler = new MyHandler(new WeakReference(this));@Overridepublic void onCreate(Bundle savedInstanceStatus) {super.onCreate(savedInstanceStatus);setContentView(R.layout.activity_main);for (int i = 0; i < names.length; i++) {views[i] = findViewById(names[i]);}new Timer().schedule(new TimerTask() {@Overridepublic void run() {handler.sendEmptyMessage(0x123);Log.d("thid", "run:" + Thread.currentThread().getId());}}, 0, 500);Log.d("thid", "onCreate:" + Thread.currentThread().getId());}
}
约束布局
P100
第二组 TextView 及其子类
View <- TextView <- EditText / Button
rich text
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:orientation="vertical"android:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="fuck java"android:textSize="20pt"android:drawableEnd="@mipmap/ic_launcher_round"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:singleLine="true"android:text="fuck java fuck java fuck java"android:textSize="20sp"android:ellipsize="middle"android:textAllCaps="true"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="email xx@192.com"android:singleLine="true"android:autoLink="email|phone"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="text word"android:shadowColor="@color/black"android:shadowDx="10.0"android:shadowDy="8.0"android:shadowRadius="3.0"android:textColor="#f00"android:textSize="18pt"/><CheckedTextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="checked text"android:textSize="20pt"android:checkMark="@drawable/ok"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="bounding text"android:textSize="24pt"android:background="@drawable/bg_border1"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="round bg"android:textSize="24pt"android:background="@drawable/bg_border2"/></LinearLayout><Buttonandroid:id="@+id/button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="212dp"android:shadowColor="#aa5"android:shadowDx="5"android:shadowDy="5"android:shadowRadius="1"android:text="Button"android:textSize="12pt"app:layout_constraintBottom_toTopOf="@+id/imageButton2"app:layout_constraintStart_toStartOf="parent" /><Buttonandroid:id="@+id/button3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="24dp"android:layout_marginBottom="48dp"android:background="@drawable/button_selector"android:text="ButtonbgXX"android:textSize="11sp"app:layout_constraintBottom_toTopOf="@+id/imageButton2"app:layout_constraintStart_toStartOf="parent" /><ImageButtonandroid:id="@+id/imageButton2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="40dp"android:layout_marginBottom="84dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintStart_toStartOf="parent"app:srcCompat="?android:attr/fingerprintAuthDrawable" /><Buttonandroid:id="@+id/button2"android:layout_width="131dp"android:layout_height="74dp"android:layout_marginStart="48dp"android:layout_marginBottom="320dp"android:background="@drawable/chat_box"android:text="股的拉开"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintStart_toEndOf="@+id/button" /></androidx.constraintlayout.widget.ConstraintLayout>
button
p109
时钟 AnalogClock 和 TextClock
TextView <- TextClock
View <- AnalogClock 重写了OnDraw方法
计时器
第三组 ImageView 及其子类
View <- ImageView <- ImageButton/ZoomButton/FloatingActionButton
第四组 AdapterView 及其子类
ViewGroup <- AdapterView
类似wechat通讯录界面
SimpleAdapter
public class MainActivity extends AppCompatActivity {private String[] names = new String[]{"namesdsf1", "弄汤", "里打找", "是空间地方"};private String[] descs = new String[]{"[ ]", "sdf", "skdjf", "sjkdfj"};private int[] imageids = new int[]{R.drawable.dice_1, R.drawable.dice_2, R.drawable.dice_3, R.drawable.dice_4};@Overridepublic void onCreate(Bundle savedInstanceStatus) {super.onCreate(savedInstanceStatus);setContentView(R.layout.activity_main);List<Map<String, Object>> listitems = new ArrayList<>();for (int i = 0; i < names.length; i++) {Map<String, Object> listitem = new HashMap<>();listitem.put("header", imageids[i]);listitem.put("personName", names[i]);listitem.put("desc", descs[i]);listitems.add(listitem);}SimpleAdapter sa = new SimpleAdapter(this, listitems,R.layout.simple_item,new String[]{"header", "personName","desc"},new int[]{R.id.header, R.id.name, R.id.desc});ListView list = findViewById(R.id.list2xx);list.setAdapter(sa);}
}
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><ImageViewandroid:id="@+id/header"android:layout_width="100dp"android:layout_height="100dp"android:paddingLeft="10dp"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><TextViewandroid:id="@+id/name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:paddingLeft="10dp"android:textColor="#f0f"android:textSize="20dp"/><TextViewandroid:id="@+id/desc"android:layout_width="wrap_content"android:layout_height="wrap_content"android:paddingLeft="10dp"android:textSize="14dp"/></LinearLayout></LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ListViewandroid:id="@+id/list2xx"android:layout_width="match_parent"android:layout_height="match_parent"android:divider="#0f0"android:dividerHeight="1dp"android:headerDividersEnabled="false" /></LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
AutoCompleteTextView 的功能和用法
从 EditText 派生
当用户输入一定字符之后,自动完成文本框会显示一个下拉菜单,当用户选择某个菜单项之后,AutoCompleteTextView自动填写该内文本框
ExapndaleListView
增加可将ListView的内容分组功能
AdapterViewFlipper
AdapterViewAnimator <- AdapterViewFlipper
自动播放之图片库
P140
叠在一起的图片
public class MainActivity extends AppCompatActivity {private int[] imageids = new int[]{R.drawable.dice_1,R.drawable.dice_2,R.drawable.dice_3,R.drawable.dice_4,R.drawable.dice_5,R.drawable.dice_6};private StackView sv;@Overridepublic void onCreate(Bundle savedInstanceStatus) {super.onCreate(savedInstanceStatus);setContentView(R.layout.activity_main);sv = findViewById(R.id.mStackView);List<Map<String, Object>> listitems = new ArrayList<>();for (int i = 0; i < imageids.length; i++) {Map<String, Object> litm = new HashMap<>();litm.put("image", imageids[i]);listitems.add(litm);}SimpleAdapter sa = new SimpleAdapter(this, listitems,R.layout.simple_item,new String[]{"image"},new int[]{R.id.stack_view_image});sv.setAdapter(sa);}public void prevfff(View v) {sv.showPrevious();}public void nextfff(View v) {sv.showNext();}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"><StackViewandroid:id="@+id/mStackView"android:layout_width="match_parent"android:layout_height="wrap_content"android:loopViews="false"/><LinearLayoutandroid:layout_width="226dp"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:id="@+id/button3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="prevfff"android:text="shangyige" /><Buttonandroid:id="@+id/button4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="nextfff"android:text="xiayige" /></LinearLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/stack_view_image"android:layout_width="100dp"android:layout_height="100dp"android:paddingLeft="10dp"/>
RecyclerView 组件
P144
package com.example.chapter1noactivity;import android.app.Person;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SimpleAdapter;
import android.widget.StackView;
import android.widget.TextView;//import androidx.activity.compose.setContent;
//import androidx.activity.enableEdgeToEdge;
//import androidx.compose.foundation.layout.fillMaxSize;
//import androidx.compose.foundation.layout.padding;
//import androidx.compose.material3.Scaffold;
//import androidx.compose.material3.Text;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
//import com.example.chapter1noactivity.ui.theme.Chapter1NoActivityTheme;public class MainActivity extends AppCompatActivity {private String[] names = new String[]{"namesdsf1", "弄汤", "里打找", "是空间地方"};private String[] descs = new String[]{"[ xxx ]", "sdf", "skdjf", "sjkdfj"};private int[] imageids = new int[]{R.drawable.dice_1,R.drawable.dice_2,R.drawable.dice_3,R.drawable.dice_4,R.drawable.dice_5,R.drawable.dice_6};private StackView sv;private RecyclerView recyclerView;private List<Person> personList = new ArrayList<>();@Overridepublic void onCreate(Bundle savedInstanceStatus) {super.onCreate(savedInstanceStatus);setContentView(R.layout.activity_main);recyclerView = findViewById(R.id.recycler);// 设置recyclerView保持固定大小,可优化其性能recyclerView.setHasFixedSize(true);LinearLayoutManager layoutManager = new LinearLayoutManager(this);// 设置滚动方向layoutManager.setOrientation(LinearLayoutManager.VERTICAL);// 为recyclerView设置布局管理器recyclerView.setLayoutManager(layoutManager);initData();RecyclerView.Adapter adapter = new RecyclerView.Adapter<PersonViewHolder>() {// 创建列表项组件的方法,使用该方法所创建的组件会被自动缓存@Overridepublic PersonViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.item, null);return new PersonViewHolder(view, this);}// 为列表项组件绑定数据的方法,每次组件重新显示出来时都会重新执行该方法@Overridepublic void onBindViewHolder(PersonViewHolder viewHolder, int i) {viewHolder.nameTv.setText(names[i]);viewHolder.descTv.setText(descs[i]);viewHolder.headerIv.setImageResource(imageids[i]);}// 该方法的返回值决定包含多少个列表项@Overridepublic int getItemCount() {return personList.size();}};recyclerView.setAdapter(adapter);}private void initData() {for (int i = 0; i < names.length; i++)this.personList.add(new Person(names[i], descs[i], imageids[i]));}class PersonViewHolder extends RecyclerView.ViewHolder {View rootView;TextView nameTv;TextView descTv;ImageView headerIv;private RecyclerView.Adapter adapter;public PersonViewHolder(View itemView, RecyclerView.Adapter adapter) {super(itemView);this.nameTv = itemView.findViewById(R.id.name);this.descTv = itemView.findViewById(R.id.desc);this.headerIv = itemView.findViewById(R.id.header);this.rootView = itemView.findViewById(R.id.item_root);this.adapter = adapter;rootView.setOnClickListener(view -> {int i = (int)(Math.random() * (personList.size() + 1));
// Person person = new Person(personList.get(i).name, personList.get(i).desc, personList.get(i).header);Person person = new Person(names[i], descs[i], imageids[i]);adapter.notifyItemInserted(2);personList.add(2, person);adapter.notifyItemRangeChanged(2, adapter.getItemCount());});rootView.setOnLongClickListener(view -> {int position = this.getAdapterPosition();// notify RecyclerView animationadapter.notifyItemRemoved(position);// rm data from basic modelMainActivity.this.personList.remove(position);// notify recyclerview exec rmadapter.notifyItemRangeChanged(position, adapter.getItemCount());return false;});}}public void prevfff(View v) {sv.showPrevious();}public void nextfff(View v) {sv.showNext();}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recycler"android:layout_marginLeft="8dp"android:layout_marginRight="8dp"android:layout_width="match_parent"android:layout_height="match_parent" />
</LinearLayout>
layout/item.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/item_root"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><ImageViewandroid:id="@+id/header"android:layout_width="100dp"android:layout_height="100dp"android:paddingLeft="10dp"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><TextViewandroid:id="@+id/name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:paddingLeft="10dp"android:textColor="#f0f"android:textSize="20dp"/><TextViewandroid:id="@+id/desc"android:layout_width="wrap_content"android:layout_height="wrap_content"android:paddingLeft="10dp"android:textSize="14dp"/></LinearLayout>
</LinearLayout>
RecyclerView.Adapter大致提供了如下方法来控制对列表项的修改
- notifyItemChanged(int position): 当position位置的数据发生改变时,程序调用该方法通知Adapter更新界面–Adapter回调对应位置的onBindViewHolder()方法进行更新
- notifyItemRangeChanged(int positonStart, int itemCount)
- notifyItemInserted(int position)
- notifyItemMoved(int fromPosition, int toPosition)
- notifyItemRangeInserted(int positionStart, int itemCount)
- notifyItemRemoved(int position)
- notifyItemRangeRemoved(int positionStart, int itemCount)
第五组UI ProgressBar及其子类
ProgressBar <- AbsSeekBar <- SeekBar/RatingBar
public class MainActivity extends AppCompatActivity {private int[] data = new int[100];private int hasData = 0;int status = 0;private ProgressBar bar;private ProgressBar bar2;static class MyHandler extends Handler {private WeakReference<MainActivity> activity;MyHandler(WeakReference<MainActivity> activity) {this.activity = activity;}@Overridepublic void handleMessage(Message msg) {if (msg.what == 0x111) {String val = String.valueOf(activity.get().status);Log.d("userinfo", val);activity.get().bar.setProgress(activity.get().status);activity.get().bar2.setProgress(activity.get().status);}}}MyHandler mHandler = new MyHandler(new WeakReference<>(this));@Overridepublic void onCreate(Bundle savedInstanceStatus) {super.onCreate(savedInstanceStatus);setContentView(R.layout.activity_main);bar = findViewById(R.id.bar);bar2 = findViewById(R.id.bar2);new Thread() {@Override public void run() {while (status < 100) {status = doWork();mHandler.sendEmptyMessage(0x111);}}}.start();}public int doWork() {data[hasData++] = (int)(Math.random() * 100);try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}return hasData;}
}
SeekBar
拖动滑块改变图片透明度
@Overridepublic void onCreate(Bundle savedInstanceStatus) {super.onCreate(savedInstanceStatus);setContentView(R.layout.activity_main);final ImageView image = findViewById(R.id.imageView);SeekBar seekBar = findViewById(R.id.seekBar);seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Override public void onProgressChanged(SeekBar bar, int progress, boolean fromUser) {image.setImageAlpha(progress);}@Override public void onStartTrackingTouch(SeekBar bar) {}@Override public void onStopTrackingTouch(SeekBar bar) {}});}
RatingBar
星条评分条
RatingBar通过星星来表示进度
第六组 ViewAnimator
FrameLayout <- ViewAnimator <- ViewSwitcher <- ImageSwitcher/TextSwitcher
FrameLayout <- ViewAnimator <- ViewFlipper
public class MainActivity extends AppCompatActivity {public static final int NUMBER_PER_SCREEN = 4;private List<DataItem> items = new ArrayList<>();private int screenNo = -1;private int screenCount = 0;private ViewSwitcher switcher;private LayoutInflater inflater;private BaseAdapter adapter = new BaseAdapter() {@Overridepublic int getCount() {if (screenNo == screenCount-1 && items.size() % NUMBER_PER_SCREEN != 0) {return items.size() % NUMBER_PER_SCREEN;} else {return NUMBER_PER_SCREEN;}}@Overridepublic DataItem getItem(int i) {return items.get(screenNo * NUMBER_PER_SCREEN + i);}// 当点击当前页面的item是该函数会被调用,i为item在grid的idx@Overridepublic long getItemId(int i) {return i;}// 当需要显示画面时,该函数会被自动调用,调用每个item调用一次,调用次数与getCount函数有关@Overridepublic View getView(int i, View convertView, ViewGroup viewGroup) {View view;ViewHolder viewHolder;if (convertView == null) {view = inflater.inflate(R.layout.labelicon, null);ImageView imageView = view.findViewById(R.id.imageview);TextView textView = view.findViewById(R.id.textview);view.setTag(viewHolder);} else {view = convertView;viewHolder = (ViewHolder) view.getTag();}viewHolder.imageView.setImageDrawable(getItem(position).drawable);viewHolder.textView.setText(getItem(position).dataName);return null;}};public static class DataItem {String dataName;Drawable drawable;DataItem(String dataName, Drawable drawable) {this.dataName = dataName;this.drawable = drawable;}}public static class ViewHolder {ImageView imageView;TextView textView;ViewHolder(ImageView imageView, TextView textView) {this.imageView = imageView;this.textView = textView;}}@Overridepublic void onCreate(Bundle savedInstanceStatus) {super.onCreate(savedInstanceStatus);setContentView(R.layout.activity_main);inflater = LayoutInflater.from(this);for (int i = 0; i < 20; i++) {String label = "" + i;Drawable drawable = getResources().getDrawable(R.mipmap.ic_launcher, null);DataItem item = new DataItem(label, drawable);items.add(item);}screenCount = items.size() % NUMBER_PER_SCREEN == 0 ? items.size() / NUMBER_PER_SCREEN : items.size() / NUMBER_PER_SCREEN + 1;switcher = findViewById(R.id.viewSwitcher);switcher.setFactory(() -> {return inflater.inflate(R.layout.slidelistview, null);});next(null);}public void next(View v) {if (screenNo < screenCount - 1) {screenNo++;switcher.setInAnimation(this, R.anim.slide_in_right);switcher.setOutAnimation(this, R.anim.slide_out_left);((GridView)switcher.getNextView()).setAdapter(adapter);switcher.showNext();}}public void prev(View v) {if (screenNo > 0) {screenNo--;switcher.setInAnimation(this, android.R.anim.slide_in_left);switcher.setOutAnimation(this, android.R.anim.slide_out_right);((GridView)switcher.getNextView()).setAdapter(adapter);switcher.showPrevious();}}
}
第七组UI对话框
AlertDialog <- ProgressDialog/DatePickerDialog/TimePickerDialog
public class MainActivity extends AppCompatActivity {@Overridepublic void onCreate(Bundle savedInstanceStatus) {super.onCreate(savedInstanceStatus);setContentView(R.layout.activity_main);Button simple = findViewById(R.id.button);Button bn = findViewById(R.id.button2);Button bn3 = findViewById(R.id.button3);simple.setOnClickListener(view -> {Toast toast = Toast.makeText(this, "simple txt", Toast.LENGTH_SHORT);Log.d("userinfo", "be");toast.show();Log.d("userinfo", "af");});bn.setOnClickListener(view -> {Toast toast = new Toast(this);toast.setGravity(Gravity.CENTER, 0, 0);ImageView image = new ImageView(this);image.setImageResource(R.drawable.dice_1);LinearLayout l1 = new LinearLayout(this);l1.addView(image);TextView textView = new TextView(this);textView.setText("uu di coco ");textView.setTextSize(24f);textView.setTextColor(Color.MAGENTA);l1.addView(textView);toast.setView(l1);toast.setDuration(Toast.LENGTH_SHORT);toast.show();});bn3.setOnClickListener((view) -> {AlertDialog.Builder builder = new AlertDialog.Builder(this).setTitle("simple dialog").setIcon(R.mipmap.ic_launcher_round).setMessage("diag test\nsecond line").setView(R.layout.login);builder.setPositiveButton("yes", (dialog, which)-> {// get login infoToast toast = Toast.makeText(this, "sclicked yes button!", Toast.LENGTH_SHORT);toast.show();});builder.setNegativeButton("niga", (dialog, which)-> {Toast toast = Toast.makeText(this, "clicked niga button!", Toast.LENGTH_SHORT);toast.show();});
// builder.setNeutralButton()builder.create().show();});}
}
android事件机制
基于监听的事件处理
内部类作为事件监听器
// 2. 事件监听器
class MyClickListener implements View.onClickListener {// 事件处理函数@Overridepublic void onClick(View v) {TextView txt = findViewById(R.id.txt); txt.setText("xxx");}
}
@Override
public void onCreate(Bundle savedInstanceState) {...// 1. 确定事件源Button bn = findViewById(R.id.bn);// 3. 注册事件处理器bn.setOnClickListener(new MyClickListener());
}
事件处理流程:
- 将事件监听器注册到事件源
- 外部动作触发事件源上的事件
- 事件源生成事件对象
- 该事件对象触发事件监听器,事件被作为参数传入事件处理器
- 调用事件处理器作出响应
外部动作| 事件2 ↗ \| 3 4 5ᐯ / ↘ ↗ 事件处理器事件源 <--1--事件监听器-->事件处理器
各种类型的事件监听器:
View.OnClickListener: 单击事件
View.OnCreateContextMenuListener: 创建上下文菜单事件的事件监听器
View.onFocusChangeListener: 焦点改变的事件监听器
View.OnKeyListener: 按键事件的事件监听器
View.OnLongClickListener: 长按事件
View.OnTouchListener: 触摸事件的时间监听器
外部类作为事件监听器
将public class MyClickListener implements View.onClickListener写在类的外部
Activity 本身作为事件监听器
public class MainActivity extends Activity implements View.OnClickListener{@Overridepublic void onCreate(xxx){}xxx@Overridepublic void onClick(View v){show.setText("bn button!");}
}
lambda表达式作为事件监听器类
bn.setOnClickListener(view -> show.setText("bn button"));
直接绑定到标签
<Buttonandroid:onClick="clickHandler"/>
基于回调的事件处理
重写GUI组件的相关方法
boolean onKeyDown(int keyCode, KeyEvent event)
boolean onKeyLongPress(int keyCode, KeyEvent event)
boolean onKeyShortcut(int keyCode, KeyEvent event)
boolean onKeyUp(int keyCode, KeyEvent event)
boolean onTouchEvent(MotionEvent event)
boolean onTrackballEvent(MotionEvent event)
public class MyButton extends Button {public MyButton(Context context, AttributeSet set) {super(context, set);}@Overridepublic boolean onTouchEvent(MotionEvent event) {super.onTouchEvent(event);Log.d("userinfo", "button true");return true; // 该方法是否能完全处理该事件// true: 事件不会传播出去// false: 事件会传播到该事件所在activity的方法}
}
响应系统设置
Configuration类
// Activity的方法
Configuration cfg = getResources().getConfiguration();
3.5 Handler消息传递机制
Android的UI操作不是线程安全的,只允许UI线程(主线程)修改Activity里的UI组件
3.5.1 Handler 类
- 在新启动的线程中发送消息
- 在主线程中获取\处理消息
public class Handler {void handleMessage(@NonNull Message msg) // 处理消息final boolean hasMessages(int what) // 消息队列中是否包含what属性为指定值的消息final boolean hasMessages(int what, @Nullable Object object)final boolean sendEmptyMessage(int what)final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis)
}
int imgs[] = {R.drawable.dice_1,R.drawable.dice_2,R.drawable.dice_3,R.drawable.dice_4,R.drawable.dice_5,R.drawable.dice_6};class MyHandler extends Handler {private WeakReference<MainActivity> activity;int currid = 0;public MyHandler(WeakReference<MainActivity> activity) {this.activity = activity;}@Overridepublic void handleMessage(Message msg) {if (msg.what == 0x1233) {activity.get().show.setImageResource(imgs[currid++ % imgs.length]);}}}MyHandler myHandler = new MyHandler(new WeakReference(this));@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);show = findViewById(R.id.imageView);new Timer().schedule(new TimerTask() {@Overridepublic void run() {myHandler.sendEmptyMessage(0x1233);}}, 0, 80);}
3.5.2 Handler, Loop, MessageQueue的工作原理
Handler把消息发给Looper管理的消息队列和处理消息;每个线程只有一个Looper,它负责管理MessageQueue(由Loop初始化),会不断的从MessageQueue中去取出消息并分给对应的Handler处理;
loop(){for(;;) {MesageQueue.next(); // 从队列中取出消息将消息分发给对应的handler处理}
}
4 Activity & Fragment
Activity <- ListActivity <- LauncherActivity\ FragmentActivity
PreferenceActivity & PreferenceFragment结合在一起,前者之负责加载选项设置头布局文件(跟元素是preference-headers),后者负责加载选项设置布局文件.
包含多个Activity的Manifest
含有intent-filter action.name=xxxMAIN actegory.name=xxxLAUNCHER的为程序的入口activity
<activityandroid:name=".MainActivity"android:exported="true"android:label="@string/title_activity_main"android:theme="@style/Theme.Chapter1NoActivity"android:configChanges="orientation|screenSize"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activity android:name=".ExpandableListActivityTest" android:label="查看星际兵种"></activity><activity android:name=".PreferenceActivityTest" android:label="设置参数"></activity>
LauncherActivity包含@Override public Intent intentForPosition(int position),当屏幕上的内容被点击时该方法会被调用
Activity的启动和关闭
Activity启动其他Activity的方法:
- startActivity(Intent intent)
- startActivityForResult(Intent, int requestCode) 以指定的请求码启动Activity,而且程序将会获取新启动的Activity返回的结果(通过重写onActivityResult()方法获取)
关闭: - finish()
- finishActivity(int requestCode): 结束以startActivityForResult(Intent intent, int requestCode)方法启动的Activity
Intent intent = new Intent(SecondActivity.this, MainActivity.class);startActivity(intent);finish();
使用Bundle在Activity之间交换数据
Intent 对象和携带 Bundle
intent.putExtras(Bundle data);
Bundle intent.getExtras()
intent.putExtra(String key, Xxx value)
intent.getXxxExtra(String key)
bundle.putXxx(String key, Xxx value)
bundle.putSerializable(String key, Serializable data)
get…
Bundle data = new Bundle();data.putSerializable("person", name.getText().toString() + " : " + passwd.getText().toString());
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtras(data);
startActivity(intent); / startActivityForResult(intent, requestCode:0);@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent intent) {if (requestCode == 0 && resultCode == 0) {Bundle data = intent.getExtras();Toast.makeText(this, data.getString("person"), Toast.LENGTH_SHORT).show();}}
_______________
intent = getIntent();
Bundle bui = intent.getExtras();
intent.getExtras();
Object data = bui.get("person");
Toast.makeText( this, data.toString(), Toast.LENGTH_LONG).show();setResult(resultCode:0, intent);
4.3 Activity生命周期
加载Activity|ᐯ+----------> onCreate| || ᐯ| onStart <----------------------- onRestart | | |用户再次启动 ᐯ |该Activity onResume <-----------------+ || | | | | ᐯ | |应用进程 运行状态 | |被终止 (其他Activity | |↑ 转入前台) | || | | || ᐯ 该Activity再 || onPause 次回到前台 || | | || ᐯ | |更高优先级的-------暂停状态--------------------+ |应用需要内存 | || 该Activity变为完全不可见 || | || ᐯ 用户再次启动该| onStop Activity使之进入前台| | || ᐯ |+-----------停止状态 ------------------------------+|该Activity结束或销毁|ᐯonDestroy|ᐯ销毁状态
public class MainActivity extends Activity
{private String TAG = "userinfo";@Override protected void onCreate(Bundle icicle) {super.onCreate(icicle);setContentView(R.layout.layout_text);Log.d(TAG, "---onCreate---");}@Override public void onStart() {super.onStart();Log.d(TAG, "---onStart---");}@Override public void onResume() {super.onResume();Log.d(TAG, "---onResume---");}@Override public void onPause() {super.onPause();Log.d(TAG, "--onPause---");}@Override public void onStop() {super.onStop();Log.d(TAG, "---onStop---");}@Override public void onDestroy() {super.onDestroy();Log.d(TAG, "---onDestroy---");}
}
4. android:launchMode=
android中 Task 负责以栈的形式管理所有的 Activity
4.4.1 standard 模式 (默认模式)
为目标Activity创建一个新的实例,并将该Activity添加到当前Task栈中,该模式不会启动新的Task,新Activity将被添加到原有的Task中
protected void onCreate(Bundle icicle) {super.onCreate(icicle);LinearLayout layout = new LinearLayout(this);layout.setOrientation(LinearLayout.VERTICAL);this.setContentView(layout);TextView tv = new TextView(this);tv.setText("Activity is :" + this.toString() + "\n" + ", Task ID is:" + this.getTaskId());Button bn = new Button(this);bn.setText("launch new MainActivity");layout.addView(tv);layout.addView(bn);bn.setOnClickListener(view -> {Intent intent = new Intent(MainActivity.this, MainActivity.class);startActivity(intent);});}| |
第三次启动: | MainActivity实例3 |
第二次启动: | MainActivity实例2 |
第一次启动: | MainActivity实例1 |+-------------------+Activity栈
当用户按下返回按钮时,系统将会"逐一"从Activity栈顶删除实例
4.4.2 singleTop 模式
当将要启动的目标Activity已经位于Task栈顶时,系统不会重新创建目标实例,而是直接复用已有的Activity实例
如果将要启动的Activity没有位于栈顶,此时系统会重新创建目标Activity的实例,并将它加载到Task盏顶
4.4.3 singleTask 模式
保证同一个Task内只有一个实例.
当要启动的Activity已经存在,但没有位于Task栈顶,系统将会把位于该Activity上面的所有Activity移除,从而使得目标Activity在栈顶.
4.4.4 singleInstance 模式
<activity android:name=".MainActivity"android:label="@string/title_activity_main"android:exported="true"android:launchMode="singleInstance"android:theme="@style/Theme.Chapter1NoActivity"android:configChanges="orientation|screenSize"><intent-filter><!-- 指定该Activity能响应Action为指定字符串的Intent --><action android:name="com.example.intent.action.XXACTION"/><category android:name="android.intent.category.DEFAULT"/></intent-filter>
</activity>
exported属性为true表明允许通过其他程序来启动Activity
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);// 隐式Intent启动Activity
Intent intent = new Intent();
intent.setAction("com.example.intent.action.XXACTION");
startActivity(intent);
4.5 Fragment
- Fragment总是作为Activity界面的组成部分.Fragmemt可调用getActivity()方法获取它所在的Activity, Activity可调用FragmentManager的findFragmentById()或findFragmentByTag()方法来获取Fragment
- 在Activity运行过程中,可调用FragmentManager的add(), remove(), replace()方法动态地添加,删除或替换Fragment
- 一个Activity可以同时组合多个Fragment;一个Fragment也可被多个Activity复用
- Fragment可以响应自己的输入时间,并拥有自己的生命周期,但它们的生命周期直接被所属的Activity控制
Fragment <-- DialogFragment / ListFragment / PreferenceFragment / WebViewFragment
开发Fragment与开发Activity非常相似.需要实现三个方法:onCreate, onCreateView(绘制界面组件是回调该方法,该方法返回的iew将作为该Fragment显示的View组件),onPause(当用户离开fragment时回调该方法)
4.5.3 Fragment与Activity通讯
为了在Activity中显示Fragment,还必须将Fragment添加到Activity中.将Fragment添加到Activity中有两种方式:
- 在布局文件中使用<fragment/>元素, 该元素的android:name属性指定Fragment的实现类
- 在代码中通过FragmentTransaction对象的add()方法添加Fragment
Activity的getSupportFragmentManager()方法可返回FragmentManager,FragmentManager对象的beginTransaction()方法即可开启并返回FragmentTransaction对象
<fragmentandroid:id="@+id/book_list"android:name="com.example.chapter1noactivity.BookListFragment"android:layout_width="100dp"android:layout_height="match_parent"android:layout_weight="1" />
// 实现Callbacks接口必须实现的方法@Overridepublic void onItemSelected(int id){// 创建Bundle,准备向Fragment传入参数Bundle arguments = new Bundle();arguments.putInt(BookDetailFragment.ITEM_ID, id);// 创建BookDetailFragment对象Log.d("userinfo", "MainActivity, onItemSelected");BookDetailFragment fragment = new BookDetailFragment();// 向Fragment传入参数fragment.setArguments(arguments);// 使用fragment替换book_detail_container容器当前显示的FragmentgetSupportFragmentManager().beginTransaction().replace(R.id.book_detail_container, fragment).commit(); // ①}
将Fragment添加到Activity之后,Fragment必须与Activity交互信息:1. Fragment获取它所在的Activity:调用Fragment的getActivity()方法即可返回它所在的Activity 2. Activity获取Fragment,调用Activity关联的FragmentManager的findFragmentById(int id)或findFragmentByTag(String tag)方法即可获取指定的Fragment
4.5.4 Fragment管理与Fragment事务
Activity管理Fragment主要依靠FragmentManager:
- 使用findFragmentById()或findFragmentByTag()获取制定Fragment
- 调用popBackStack()将Fragment从后台栈中弹出
- 调用addOnBackStackChangeListener()注册一个监听器,用于监听后台栈的变化
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();ExampleFragment newFragment = new ExampleFragment();
fragmentTransaction.replace(R.id.fragment_container, newFragment);
// 将事务(操作)添加到Back栈,允许用户按BACK键返回到替换Fragment之前的状态
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
chapter 5 Intent, IntentFilter
5.1 Intent对象
Activity, Service, BroadcastReceiver这三个组件都可依赖Intent来启动,Intent封装了程序想要启动程序的意图和通讯信息
| 类型 | 启动方法 |
|---|---|
| Activity | startActivity(Intent); startActivityForResult(Intent, int); |
| Service | ComponentName startService(Intent); boolean bindService(Intent, ServiceConnection conn, int flags); |
| BroadcastReceiver | sendBroadcast(Intent); sendBroadcast(Intent, String); sendOrderedBroadcast(Intent, String); … |
5.2 Intent属性及 intent-filter 配置
Compoent 属性
为Intent指定了Component属性
@Override protected void onCreate(Bundle savedInstanceState)
{super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button bn = findViewById(R.id.bn);bn.setOnClickListener(view -> {ComponentName comp = new ComponentName(MainActivity.this, SecondActivity.class);Intent intent = new Intent();intent.setComponent(comp);// => new Intent(this, SecondActivity.class)startActivity(intent);});
}
SecondActivity
ComponentName comp = getIntent().getComponent();
组件包名 comp.getPackageName()
组件类名 comp.getClassName()
String action = getIntent().getAction()
Set<String> cates = getIntent().getCategories()
Action, Category属性
Action和Category都是普通字符串,Action代表intent所要完成的一个抽象"动作",Category为Action添加额外信息. 具体启动哪个Activity由<intent-filter…/>配置.
1个intent只能包含一个action,但可有多个category
Intent intent = new Intent();
intent.setAction("action is a string. com.chapter1")
startActivity(intent);
// 具体启动那个Activity由<intent-filter.../>配置
<activity android:name=".EmptyActivity" android:label="empty activity" android:exported="true"><intent-filter>表示该Activity响应 intent.action==xxx 的intent<action android:name="android.intent.action.YYYYY" /> <category android:name="android.intent.category.DEFAULT"/></intent-filter>
</activity>
Intent代表了启动某个程序组件的"意图",它不仅能启动本应用内的组件也可启动Android系统的其他应用的程序组件,包括系统自带的程序组件(只要权限允许)
返回HOME桌面
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
Data, Type 属性
Data属性用于向Action属性提供操作的数据.Data属性接受一个Uri对象
Uri字符串格式: scheme://host:port/path
Type属性用于指定该Data属性所制定Uri对应的MIME类型 abc/xyz
intent.setData(Uri.parse("lee://www.abc:8888/test"));
intent.setType("abc/xyz");
intent.setDataAndType(Uri.parse("lee://www.abc:8888/test"), "abc/xyz");
<data android:mimeType=""android:scheme=""android:host=""android:port=""android:path=""android:pathPrefix=""android:pathPattern=""/>
实例:使用Action, Data属性启动系统Activity
一旦为Intent同时指定了Action属性,Data属性, Android就可根据指定的数据类型来启动特定的应用程序,并对制定数据执行相应的操作.
- ACTION_VIEW content://com.android.contacts/contacts/1 : 显示标识为1的联系人的信息
- ACTION_EDIT content://com.android.contacts/contacts/1 : 编辑标识为1的联系人的信息
- ACTION_DIAL content://com.android.contacts/contacts/1 : 显示想标识为1的联系人拨号的界面
- ACTION_VIEW tel:123 :显示向指定号码123拨号的界面
- ACTION_DIAL tel:123 :显示向制定号码123拨号的界面
- ACTION_VIEW content://contacts/people/ :显示所有联系人列表的信息
detailIntent = new Intent();
detailIntent.setAction(Intent.ACTION_VIEW);
detailIntent.setData(Uri.parse("http://www.bing.com"));detailIntent = new Intent();
detailIntent.setAction(Intent.ACTION_EDIT);
detailIntent.setData(Uri.parse("content://com.android.contacts/contacts/1"));detailIntent = new Intent();
detailIntent.setAction(Intent.ACTION_DIAL);
detailIntent.setData(Uri.parse("tel:138000000"));
Extra 属性
用于在多个Action之间进行数据交换,应该是一个 Bundle 对象
Flag 属性
6 Android 应用资源
- 界面布局文件:xml文件
- 程序源文件:应用中的Activity, Service, BroadcastReceiver, ContentProvider四大组件
- 资源文件:各种xml,包括png,jpj.gif等
将代码中用到的常量集中/统一存放在类/接口中,实现一定的解耦,但是仍可提高.Android允许把应用中用到的各种资源,如字符串,谈色,数组,菜单等都集中存放到/res/目录中定义,应用则直接使用这些资源中定义的值. assets目录下的资源代表应用无法直接访问,须通过AssetManager获取;/res/下的资源,androidSDK 会在编译时自动在R.java文件中为这些资源创建索引,程序可直接通过R资源清单类进行访问.
6.1 应用资源
- 在源程序中使用资源清单项
[<package_name>.]R.<resource_type>.<resource_name>// 从drawable资源中加载图片,并设为该窗口的背景 window.setBackgroundDrawableResource(R.drawable.back); // 从string资源中获取制定字符串资源,并设置该窗口的标题 window.setTitle(resources.getText(R.string.main_title)); // 获取制定的TextView组件,并设置该组件显示string资源中的指定字符串资源 TextView msg = findViewById(R.id.msg); msg.setText(R.string.hello_message); - 在源代码中访问实际资源
R资源清单类的项只是一个int值,不是实际的资源对象,若想获取实际资源对象需通过Resources类他提哦那个了两类方法:
- getXxx(int id);
- getAssets();
// 直接调用Activity的getResources()获取Resources对象 Resources res = getResources(); // 获取字符串资源 String mainTitle = res.getText(R.string.main_title); // 获取drawable资源 Drawable logo = res.getDrawable(R.drawable.logo); // 获取数组资源 int[] arr = res.getIntArray(R.array.books); - 在XML文件中使用资源
@[<package_name:>]<resource_type>/<resource_name>
5.2 定义字符串 颜色 尺寸资源文件 数组
这些资源都位于/res/values/目录下
strings.xml
<resources><string name="app_name">LaoliClock</string><string name="title_activity_main">MainActivityxx</string><string name="button_normal">normal</string><string name="button_shrink">shrink</string><string name="button_stretch">stretch</string>
</resources>
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources><color name="red">#f00</color><color name="green">#0f0</color><color name="blue">#00f</color><color name="yellow">#ff0</color><color name="pink">#f0f</color><color name="teal">#0ff</color><color name="grey">#888</color>
</resources>
dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources><dimen name="spacing">8dp</dimen><!-- 定义GridView组件中每个单元格的宽度、高度 --><dimen name="cell_width">60dp</dimen><dimen name="cell_height">66dp</dimen><!-- 定义主程序标题的字体大小 --><dimen name="title_font_size">18sp</dimen>
</resources>
integer
<?xml version="1.0" encoding="utf-8"?>
<resources><integer name="my_size">32</integer><integer name="book_numbers">12</integer>
</resources>
[<package_name>.]R.integer.integer_name@[<package_name>:]integer/integer_nameResources res = getResources();
int mySize = res.getInterger(R.integer.my_size);
arrays.xml
<?xml version="1.0" encoding="utf-8"?>
<resources><!-- 定义一个Drawable数组 --><array name="plain_arr"><item>@color/c1</item><item>@color/c2</item><item>@color/c3</item></array><!-- 定义字符串数组 --><string-array name="string_arr"><item>@string/c1</item><item>@string/c2</item><item>@string/c3</item></string-array><!-- 定义字符串数组 --><string-array name="books"><item>Java</item><item>前端开发</item><item>Android</item></string-array>
</resources>
String[] texts = getResources().getStringArray(R.array.string_arr);
TypedArray icons = getResources().obtainTypedArray(R.array.plain_arr);
6.4 Drawable资源
该资源可以是png,jgp,gif,xml. 保存在/res/drawable/目录下 /res/drawable-ldpi/, /res/drawable-mdpi/ , /res/drawable-hdpi/ , /res/drawable-xhdpi/
[<package_name>.]R.drawable.<file_name>
@[<package_name>:]drawable/file_namegetDrawable(int id);
6.4.2 StateListDrawable资源
高亮显示正在输入的文本框
my_image.xml
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><!-- 指定获得焦点时的颜色 --><item android:state_focused="true"android:color="#f44"/><!-- 指定失去焦点时的颜色 --><item android:state_focused="false"android:color="#ccf"/>
</selector>
定义能改变textcolor的文本框
<EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content" android:textColor="@drawable/my_image"/>
通过使用StateListDrawable不仅可以让文本框的文字颜色岁文本框状态的改变而切换,也可让按钮的北京前景随状态的改变而切换. StateListDrawable的功能非常灵活,可让各种组件的背景前景随状态的改变而切换
6.4.3 LayerDrawable 资源
定制拖动条的外观
drawable/my_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><item android:id="@android:id/background"android:drawable="@drawable/grow"/><item android:id="@android:id/progress"android:drawable="@drawable/ok"/>
</layer-list>
drawable/layer_logo.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><item><bitmap android:gravity="center" android:src="@drawable/ic_logo"/></item><item android:left="40dp" android:top="40dp"><bitmap android:gravity="center" android:src="@drawable/ic_logo"/></item><item android:left="80dp" android:top="80dp"><bitmap android:gravity="center" android:src="@drawable/ic_logo"/></item>
</layer-list>
layout/activit_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginLeft="16dp"android:layout_marginRight="16dp"android:divider="?android:attr/dividerHorizontal"android:orientation="vertical"android:showDividers="middle"><!-- 添加一个拖动条 --><SeekBarandroid:layout_width="match_parent"android:layout_height="wrap_content"android:max="100"android:progressDrawable="@drawable/my_bar"/><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/layer_logo"/>
</LinearLayout>
6.4.6 ShapeDrawable资源
drawable/my_shape_1.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><!-- 设置填充颜色 --><solid android:color="#fff"/><!-- 设置四周的内边距 --><padding android:left="7dp"android:top="7dp"android:right="7dp"android:bottom="7dp" /><!-- 设置边框 --><stroke android:width="3dip" android:color="#ff0" />
</shape>
drawable/my_shape_2.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><!-- 定义填充渐变颜色 --><gradientandroid:startColor="#FFFF0000"android:endColor="#80FF00FF"android:angle="45"/><!-- 设置内填充 --><padding android:left="7dp"android:top="7dp"android:right="7dp"android:bottom="7dp" /><!-- 设置圆角矩形 --><corners android:radius="8dp" />
</shape>
drawable/my_shape_3.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="oval"><!-- 定义填充渐变颜色 --><gradientandroid:startColor="#ff0"android:endColor="#00f"android:angle="45"android:type="sweep"/><!-- 设置内填充 --><padding android:left="7dp"android:top="7dp"android:right="7dp"android:bottom="7dp" /><!-- 设置圆角矩形 --><corners android:radius="8dp" />
</shape>
6.4.5 ClipDrawable 资源
图片进度条
layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ImageViewandroid:id="@+id/image"android:layout_width="match_parent"android:layout_height="wrap_content"android:scaleType="fitStart"android:src="@drawable/my_clip" />
</LinearLayout>
drawable/my_clip.xml
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"android:clipOrientation="vertical"android:drawable="@drawable/background"android:gravity="center">
</clip>
public class MainActivity extends Activity{@Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ImageView imageView = findViewById(R.id.image);// 获取图片所显示的ClipDrawable对象final ClipDrawable drawable = (ClipDrawable) imageView.getDrawable();class MyHandler extends Handler {@Override public void handleMessage(Message msg) {// 如果该消息是本程序所发送的if (msg.what == 0x1233) {// 修改ClipDrawable的level值drawable.setLevel(drawable.getLevel() + 200);}}}final Handler handler = new MyHandler();final Timer timer = new Timer();timer.schedule(new TimerTask() {@Override public void run() {Message msg = new Message();msg.what = 0x1233;// 发送消息,通知应用修改ClipDrawable对象的level值handler.sendMessage(msg);// 取消定时器if (drawable.getLevel() >= 10000) {timer.cancel();}}}, 0, 300);}
}
6.4.6 AnimationDrawable资源
6.5 属性动画资源 Property Animation
6.6 使用原始XML资源; Layout资源; Menu资源
应用的初始化配置信息推荐使用xml保存,放在/res/xml/下
6.9 样式和主题 style theme
用于美化应用. 存放在/res/values/下
定义样式:
<?xml version="1.0" encoding="UTF-8"?>
<resources><!-- AS创建项目时原有的主题 --><style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar"></style><!-- 定义一个样式,指定字体大小、字体颜色 --><style name="style1"><item name="android:textSize">20sp</item><item name="android:textColor">#00d</item></style><!-- 定义一个样式,继承前一个颜色 --><style name="style2" parent="@style/style1"><item name="android:background">#ee6</item><item name="android:padding">8dp</item><!-- 覆盖父样式中指定的属性 --><item name="android:textColor">#000</item></style><style name="CrazyTheme"><item name="android:windowNoTitle">true</item><item name="android:windowFullscreen">true</item><item name="android:windowFrame">@drawable/window_border</item><item name="android:windowBackground">@drawable/star</item></style>
</resources>
使用样式
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><!-- 指定使用style1的样式 --><EditTextstyle="@style/style1"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="@string/style1" /><!-- 指定使用style2的样式 --><EditTextstyle="@style/style2"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="@string/style2" />
</LinearLayout>
主题与样式的区别:
- 主题不能作用于单个的View组件,主题应该对整个应用中的所有Activity起作用,或对指定的Activity起作用
- 主题定义的格式应该是改变窗口外观的格式,例如窗口标题,窗口边框等.
给所有的窗口添加边框,背景
/res/values/my_style.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="TestTheme"><item name="android:windowNoTitle">true</item><item name="android:windowFullscreen">true</item><item name="android:windowFrame">@drawable/window_border</item><item name="android:windowBackground">@drawable/a_picture</item>
</style>
</resources>
window_border.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><!-- 设置填充颜色 --><solid android:color="#0fff" /><!-- 设置四周的内边距 --><padding android:bottom="7dp"android:left="7dp"android:right="7dp"android:top="7dp" /><!-- 设置边框 --><stroke android:width="10dp"android:color="#f00" />
</shape>
使用:
1. manifest文件:<application android:theme="@style/TestTheme"
<activity android:theme="@style/TestTheme"2. 代码中Activity的方法 setTheme(R.style.TestTheme);
安卓内定主题:@style/Theme.xxx
6.10 属性资源
如果用户开发的自定义View组件也需要指定属性,就需要属性资源的帮助了.
6.11 使用原始资源
类似于声音文件及其它各种类型的文件,只要android没有为之提供专门的支持,这种资源都被成为原始资源. Android的原始资源可放在如下两个地方:
- /res/raw/,Android SDK会处理该目录下的原始资源,AndroidSDK会在R清单类中为该目录下的资源生成一个索引项.
- 位于/assets/目录下,该目录下的资源是更彻底的原始资源. Android应用需要通过AssetManager来管理该目录下的原始资源.
public class MainActivity extends Activity {private MediaPlayer player1, player2;@Override protected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);player1 = MediaPlayer.create(this, R.raw.bomb);AssetManager am = getAssets();try{AssetFileDescriptor afd = am.openFd("shot.mp3");player2 = new MediaPlayer();player2.setDataSource(afd.getFileDescriptor());player2.prepare();} catch (IOException e){e.printStackTrace();}Button b1 = findViewById(R.id.button3);b1.setOnClickListener(view -> {player1.start();});Button b2 = findViewById(R.id.button5);b2.setOnClickListener(view -> player2.start());}
}
6.12 国际化资源
6.13 适应不同屏幕的资源
xxx
9 使用ContentProvider实现数据共享
10 Service和BroadcastReceiver
10.1 Service
Service组件也是可执行的程序,他也有自己的生命周期.创建,配置Service与创建,配置Activity的过程基本相似.
public class FirstService extends Service {@Overridepublic IBinder onBind(Intent intent){//bindService时调用return null;}@Overridepublic void onCreate(){super.onCreate();System.out.println("Service is Created");// 第一次启动时调用}@Overridepublic int onStartCommand(Intent intent, int flags, int startId){System.out.println("Service is Started");return START_STICKY;// 每次调用 startService 时调用}@Overridepublic void onDestroy(){super.onDestroy();System.out.println("Service is Destroyed");}
}// 启动一个服务. 方法1
bn1.setOnClickListener(view -> {startService(intent);});
// stopService(intent)// 启动一个服务. 方法2bn1.setOnClickListener(view -> {bindService(intent, conn, Service.BIND_AUTO_CREATE);});bn3.setOnClickListener(view -> {unbindService(conn);});bn2.setOnClickListener(view -> {Toast.makeText(this, "Service count: "+binder.getCount(), Toast.LENGTH_SHORT).show();});private FirstService.MyBinder binder;private ServiceConnection conn = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {Log.d(TAG, "MainActivity. onServiceConnected");binder = (FirstService.MyBinder)iBinder;}@Overridepublic void onServiceDisconnected(ComponentName componentName) {Log.d(TAG, "MainActivity onServiceDisconnected");}};------------------------private int count;private MyBinder binder = new MyBinder();@Overridepublic IBinder onBind(Intent intent){return binder;}@Overridepublic boolean onUnbind(Intent intent){return true;}class MyBinder extends Binder{public int getCount() {return FirstService.this.count;}}
- 通过Contenxt的startService()方法启动Service,访问者与Service之间没有关联,即使访问者退出了,Service也仍然运行
- 通过Context的bindService()方法:访问者与之绑定在一起,访问者退出Service也退出
10.1.5 IntentService
@Deprecated
- Service 不会专门启动一个单独的进程,Service与它所在应用位于同一个进程中.
- Service 不是一条新的线程,因此不应该在Service中直接处理耗时任务
- IntentService会创建单独的worker线程来处理所有的Intent请求.
- IntentService会创建单独的worker线程来处理onHandleIntent()方法实现的代码,
- 当所有请求处理完后,IntentService会自动停止
- IntentService实现,只需重写onHandleIntent()方法即可
10.2 跨进程调用 Service(AIDL Service)
Android 需要AIDL(Android Interface Definition Language, Android接口定义语言)来定义远程接口.
先定义一个接口,然后为该接口提供一个实现类即可
使用方法:
- 定义.aidl文件
在main目录上鼠标右键new->AILD(需要先在build.gradle中添加 android.buildFeatures.aidl 为true) - 在IMyAidlInterface.aidl中添加接口文件
package com.example.chapter1noactivity; interface IMyAidlInterface {String getColor();double getWeight(); } - 新建一个Service并将其添加入manifest文件中
Android系统本身提供了常见的远程服务
TelephonyManager是一个管理手机通话状态,电话网络信息的服务类,该类提供了大量的getXxx()方法获取电话网络的相关信息.
TelephonyManager tManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
14 管理Android系统桌面
- setBitmap(Bitmap bitmap): 将壁纸设置为bitmap所代表的位图
- setResource(int resid): 将壁纸设置为resid资源所代表的图片
- setStream(InputStream data): 将壁纸设置为data数据所代表的图片
14.1 动态壁纸 Live Wallpapers
动态壁纸的动画由程序实时绘制
- 开发一个子类继承WallpaperService基类
- 集成WallpaperService积累时必须重写onCreateEngine()方法,该方法返回WallpaperService.Engine子类对象
- 开发者需要实现WallpaperService.Engine子类,并重写其中的onVisibilityChanged(boolean visible), onOffsetsChanged()方法.
蜿蜒壁纸
xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><com.example.chapter1noactivity.draw.DrawViewandroid:layout_width="match_parent"android:layout_height="match_parent" /><LinearLayoutandroid:id="@+id/root_layout"android:layout_width="409dp"android:layout_height="736dp"android:layout_marginTop="4dp"android:orientation="vertical"app:layout_constraintTop_toTopOf="parent"tools:ignore="MissingConstraints"tools:layout_editor_absoluteX="1dp"><TextViewandroid:id="@+id/textView"android:layout_width="190dp"android:layout_height="52dp"android:layout_marginStart="116dp"android:layout_marginTop="236dp"android:text="" /><Spaceandroid:layout_width="wrap_content"android:layout_height="wrap_content" /><Buttonandroid:id="@+id/button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="144dp"android:layout_marginTop="28dp"android:text="Button Me" /><FrameLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"></FrameLayout></LinearLayout><TableLayoutandroid:id="@+id/TableLayout01"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_constraintBottom_toBottomOf="parent"android:shrinkColumns="1"android:stretchColumns="2"><Buttonandroid:id="@+id/button2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/app_name" /><TableRowandroid:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/button3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/button_normal" /><Buttonandroid:id="@+id/button4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/button_shrink" /><Buttonandroid:id="@+id/button5"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/button_stretch" /></TableRow></TableLayout><TableLayoutandroid:id="@+id/TableLayout02"android:layout_width="409dp"android:layout_height="385dp"android:collapseColumns="1,2"app:layout_constraintBottom_toBottomOf="parent"tools:ignore="MissingConstraints"><Buttonandroid:id="@+id/button6"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/app_name" /><TableRowandroid:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/button7"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/button_normal" /><Buttonandroid:id="@+id/button8"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/button_shrink" /><Buttonandroid:id="@+id/button9"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/button_stretch" /></TableRow></TableLayout><TableLayoutandroid:id="@+id/TableLayout03"android:layout_width="match_parent"android:layout_height="wrap_content"app:layout_constraintBottom_toBottomOf="parent"android:stretchColumns="1,2"><Buttonandroid:id="@+id/button10"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/app_name" /><TableRowandroid:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/button11"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/button_normal" /><Buttonandroid:id="@+id/button12"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/button_shrink" /><Buttonandroid:id="@+id/button13"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="333ff" /></TableRow><TableRow><Buttonandroid:id="@+id/button14"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/button_normal" /><Buttonandroid:id="@+id/button15"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="xxxxxxxxxxxxxxx" /></TableRow></TableLayout></androidx.constraintlayout.widget.ConstraintLayout>
java
MainActivity.java
package com.example.chapter1noactivity;import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;//import androidx.activity.compose.setContent;
//import androidx.activity.enableEdgeToEdge;
//import androidx.compose.foundation.layout.fillMaxSize;
//import androidx.compose.foundation.layout.padding;
//import androidx.compose.material3.Scaffold;
//import androidx.compose.material3.Text;
import androidx.appcompat.app.AppCompatActivity;
//import com.example.chapter1noactivity.ui.theme.Chapter1NoActivityTheme;//import android.widget.//public class MainActivity extends AppCompatActivity {
// private int clickNum = 0;
//
// @Override
// public void onCreate(Bundle saveInstanceState) {
// super.onCreate(saveInstanceState);
// setContentView(R.layout.activity_main);
//
// TextView tv = findViewById(R.id.textView);
// tv.setText("hello android - [" + clickNum + "] " + new java.util.Date());
//
//
// Button myButton = (Button) findViewById(R.id.button);
// myButton.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// clickNum++;
// tv.setText("hello android - [" + clickNum + "] " + new java.util.Date());
// }
// });
// }
//
//
// public void clickHandler(View source) {
// TextView tv = findViewById(R.id.button);
// clickNum++;
// tv.setText("hello android - [" + clickNum + "] " + new java.util.Date());
//
// }
//}public class MainActivity extends AppCompatActivity {private int clickNum = 0;private int[] imageArr = new int [] {R.drawable.ic_launcher_background, R.drawable.ic_launcher_foreground};private int currentImg = 0;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
// LinearLayout main = new LinearLayout(this);setContentView(R.layout.activity_main);LinearLayout main = findViewById(R.id.root_layout);ImageView image = new ImageView(this);main.addView(image);image.setImageResource(imageArr[0]);image.setOnClickListener(view -> { image.setImageResource(imageArr[++currentImg % imageArr.length]); });Button myButton = (Button) findViewById(R.id.button);TextView tv = findViewById(R.id.textView);myButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {clickNum++;tv.setText("hello android - [" + clickNum + "] " + new java.util.Date());}});}
}// 绘制跟随手指移动的小球
public class MainActivity extends AppCompatActivity {@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 可将下面的绘制小球放入xml中,实现代码和layout解耦// <com />LinearLayout main = findViewById(R.id.root_layout);DrawView draw = new DrawView(this);draw.setMinimumWidth(300);draw.setMinimumHeight(500);main.addView(draw);}
}
DrawView.java
package com.example.chapter1noactivity.draw;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;public class DrawView extends View {private float currentX = 40f;private float currentY = 50f;// 创建并定义画笔private final Paint p = new Paint();public DrawView(Context context) {super(context);}public DrawView(Context context, AttributeSet set) {super(context, set);}// 当该组件将要绘制它的内容时触发@Overridepublic void onDraw(Canvas canvas) {super.onDraw(canvas);p.setColor(Color.RED);canvas.drawCircle(currentX, currentY, 15F, p);}// 为该组件的touch事件重写事件处理方法@Overridepublic boolean onTouchEvent(MotionEvent event) {// 获取触点位置并赋值currentX = event.getX();currentY = event.getY();// 通知组件重绘自己invalidate();// 返回true表明该处理方法已经处理该事件return true;}
}相关文章:
疯狂安卓入门,crayandroid
系列文章目录 文章目录 系列文章目录第一组 ViewGroup 为基类帧布局约束布局 第二组 TextView 及其子类button时钟 AnalogClock 和 TextClock计时器 第三组 ImageView 及其子类第四组 AdapterView 及其子类AutoCompleteTextView 的功能和用法ExapndaleListViewAdapterViewFlipp…...
批量测试IP和域名联通性
最近需要测试IP和域名的联通性,因数量很多,单个ping占用时间较长。考虑使用Python和Bat解决。考虑到依托的环境,Bat可以在Windows直接运行。所以直接Bat处理。 方法1 echo off for /f %%i in (E:\封禁IP\ipall.txt) do (ping %%i -n 1 &…...
Python——计算机网络
一.ip 1.ip的定义 IP是“Internet Protocol”的缩写,即“互联网协议”。它是用于计算机网络通信的基础协议之一,属于TCP/IP协议族中的网络层协议。IP协议的主要功能是负责将数据包从源主机传输到目标主机,并确保数据能够在复杂的网络环境中正…...
一招解决Pytorch GPU版本安装慢的问题
Pytorch是一个流行的深度学习框架,广泛应用于计算机视觉、自然语言处理等领域。安装Pytorch GPU版本可以充分利用GPU的并行计算能力,加速模型的训练和推理过程。接下来,我们将详细介绍如何在Windows操作系统上安装Pytorch GPU版本。 查看是否…...
股票交易所官方api接口有哪些?获取和使用需要满足什么条件
炒股自动化:申请官方API接口,散户也可以 python炒股自动化(0),申请券商API接口 python炒股自动化(1),量化交易接口区别 Python炒股自动化(2):获取…...
MoonSharp 文档五
目录 13.Coroutines(协程) Lua中的协程 从CLR代码中的协程 从CLR代码中的协程作为CLR迭代器 注意事项 抢占式协程 14.Hardwire descriptors(硬编码描述符) 为什么需要“硬编码” 什么是“硬编码” 如何进行硬编码 硬编…...
框架源码私享笔记(02)Mybatis核心框架原理 | 一条SQL透析核心组件功能特性
最近在思考一个问题:如何能够更好的分享主流框架源码学习笔记(主要是源码部分)?让有缘刷到的同学既可以有所收获,还能保持对相关技术架构探讨学习热情和兴趣。以及自己也保持较高的分享热情和动力。 今天尝试用一个SQL查询作为引…...
如何重置 MySQL root 用户的登录密码?
重置 MySQL root 密码的核心步骤是绕过权限验证登录数据库并更新密码字段。以下是具体方法: 方法一:通过 --SKIP-GRANT-TABLES 模式修改密码 停止 MySQL 服务 Windows:在命令行执行 net stop mysql(服务名可能为 mysql80 或 mysql…...
ArrayList底层结构和源码分析笔记
参考视频:韩顺平Java集合 ArrayList特点 ArrayList 可以加入 null,包括多个。 ArrayList 是由数组来实现数据存储的 ArrayList 基本等同于 Vector,除了 ArrayList 是线程不安全(执行效率高)。在多线程情况下…...
Centos离线安装gcc
文章目录 Centos离线安装gcc1. gcc是什么?2. gcc下载地址3. gcc的安装4. 安装结果验证 Centos离线安装gcc 1. gcc是什么? GCC(GNU Compiler Collection)是 GNU 项目下的开源编译器套件,主要用于将 C、C 等编程语言的源…...
flutter 图片资源路径管理
1. 创建统一资源管理类 创建一个单独的 Dart 文件(比如 manager.dart),将所有图片路径集中管理。这样在引用图片时,不需要每次都手动输入完整路径,只需通过常量引用即可。 //manager.dartclass Manager { static co…...
[内网渗透] 红日靶场2
环境配置 靶场地址: http://vulnstack.qiyuanxuetang.net/vuln/wiki/ 环境配置可以看这个: https://www.bilibili.com/video/BV1De4y1a7Ps/?spm_id_from333.337.search-card.all.click&vd_sourcecf73ac8de9b7c0322b1bccf77de91c5dNAT模式分配111段, DHCP也要更改 再添加…...
【cocos creator】游戏优化,内存,性能,包体积大小,加载,drawcall优化
参考: https://blog.csdn.net/qq_47012987/article/details/140169024 内存泄露排查 使用chrome测试cocos creator内存泄漏问题手游内存优化cocos creator优化Creator资源自动释放逻辑:所有 cc.Asset 实例都拥有成员函数 addRef 和 decRef,分…...
MySQL 企业版 TDE加密后 测试和问题汇总
一、测试keyring file 1.1 当keyring file文件丢失或者被篡改 结论:不影响当前正在运行的数据库,但是在重启服务后会启动失败出现报错。 tail -n 100 /var/log/mysql/error.log 报错信息如下: 2025-03-12T08:04:54.668847Z 1 [ERROR] [M…...
Unity 封装一个依赖于MonoBehaviour的计时器(下) 链式调用
[Unity] 封装一个依赖于MonoBehaviour的计时器(上)-CSDN博客 目录 1.加入等待间隔时间"永远执行方法 2.修改为支持链式调用 实现链式调用 管理"链式"调度顺序 3.测试 即时方法编辑 "永久"方法 链式调用 4.总结 1.加入等待间隔时间&qu…...
petalinux环境下给linux-xlnx源码打补丁
在调试88e1512芯片时官方驱动无法满足我的应用方式,因此修改了marvell.c源码,但是在做bsp包重新创建新工程时发现之前的修改没有生效,因此查找了一下资料发现可以通过打补丁的方式添加到工程文件中,便于管理。 操作步骤 一、获取…...
套接字缓冲区以及Net_device
基础网络模型图 一般网络设计分为三层架构和五层设计: 一、三层架构 用户空间的应用层 位于最上层,是用户直接使用的网络应用程序,如浏览器、邮件客户端、即时通讯软件等。这些程序通过系统调用(如 socket 接口)向内核…...
2024下半年真题 系统架构设计师 案例分析
案例一 软件架构 关于人工智能系统的需求分析,给出十几个需求。 a.系统发生业务故障时,3秒内启动 XXX,属于可靠性 b.系统中的数据进行导出,要求在3秒内完成,属于可用性 c.质量属性描述,XXX,属…...
AI学习——深度学习核心技术深度解析
一、深度学习的本质与核心思想 定义:通过多层非线性变换,自动学习数据层次化表征的机器学习方法 核心突破: 表征学习:自动发现数据的内在规律,无需人工设计特征端到端学习:直接从原始输入到最终输出&…...
c++介绍智能指针 十二(2)
智能指针share_ptr,与unique_ptr不同,多个shar_ptr对象可以共同管理一个指针,它们通过一个共同的引用计数器来管理指针。当一个智能指针对象销毁时,计数器减一。当计数器为0时,会将所指向的内存对象释放。 #include<memory>…...
西门子S7-1200 PLC远程调试技术方案(巨控GRM532模块)
三步快速实现远程调试 硬件部署 准备西门子S7-1200 PLC、巨控GRM552YW-C模块及编程电脑。GRM552YW-C通过网口与PLC连接,支持4G/5G/Wi-Fi/有线网络接入,无需复杂布线。 软件配置 安装GVCOM3配置软件,注册模块(输入唯一序列号与密…...
vue启动 localhost无法访问
1. localhost 和 127.0.0.1 虽然都指向本机,但它们有细微的区别: - localhost 是一个域名,需要通过 DNS 解析或本地 hosts 文件解析为 IP 地址 - 127.0.0.1 是直接的 IP 地址,不需要解析过程 2. 无法访问 localhost 的可…...
Mac上更改默认应用程序
Mac上为某些文件设置默认打开应用的时候,刚开始是通过打开方式,其他里面,勾选始终以此方式打开,但实际上这个功能并不太好用,经常会让人误以为已经设置好了。但是实际上只是在当前目录起作用。真正解决这个问题可以按照…...
【开源+代码解读】Search-R1:基于强化学习的检索增强大语言模型框架3小时即可打造个人AI-search
大语言模型(LLMs)在处理复杂推理和实时信息检索时面临两大挑战:知识局限性(无法获取最新外部知识)和检索灵活性不足(传统方法依赖固定检索流程)。现有方法如检索增强生成(RAG)和工具调用(Tool-Use)存在以下问题: RAG:单轮检索导致上下文不足,无法适应多轮交互场景…...
贪心算法和遗传算法优劣对比——c#
项目背景:某钢管厂的钢筋原材料为 55米,工作需要需切割 40 米(1段)、11 米(15 段)等 4 种规格 ,现用贪心算法和遗传算法两种算法进行计算: 第一局:{ 40, 1 }, { 11, 15…...
网络安全防护总体架构 网络安全防护工作机制
1 实践内容 1.1 安全防范 为了保障"信息安全金三角"的CIA属性、即机密性、完整性、可用性,信息安全领域提出了一系列安全模型。其中动态可适应网络安全模型基于闭环控制理论,典型的有PDR和P^2DR模型。 1.1.1 PDR模型 信息系统的防御机制能…...
SpringCloud带你走进微服务的世界
认识微服务 随着互联网行业的发展,对服务的要求也越来越高,服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢? 单体架构 单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部…...
Python设计模式 - 建造者模式
定义 建造者模式是一种创建型设计模式,主要用于构建包含多个组成部分的复杂对象。它将对象的构建过程与表示分离,使得同样的构建过程可以创建不同的对象表示。 结构 抽象建造者(Builder):声明创建产品的各个部件的方…...
在 Ubuntu 上安装和配置 Docker 的完整指南
Docker 是一个开源的平台,旨在简化应用程序的开发、部署和运行。通过将应用程序及其依赖项打包到容器中,Docker 确保应用程序可以在任何环境中一致地运行。 目录 前言安装前的准备安装 Docker 步骤 1:更新包索引步骤 2:安装必要…...
网络安全之数据加密(DES、AES、RSA、MD5)
刚到公司时,我的工作就是为app端提供相应的接口。之前app使用的是PHP接口,对数据加密方面做得比较少。到使用java接口时,老大开始让我们使用DES加密,进行数据传输,但是后来觉得DES是对称加密,密钥存在客户端…...
