Android开发基础入门(一):UI与基础控件
ccwgpt 2025-07-08 17:09 20 浏览 0 评论
Android基础入门
前言:
从今天开始,我们开始分享Android客户端开发的基础知识。
一、工具指南
工欲善其事必先利其器,我们首先介绍一下开发Android常用的集成开发环境。
小雨在上大学期间,开发android应用用的还是Eclipse+ADT,后来接触到了Google推出的Android Studio搭配Gradle真正感受到了IDE强大。
1.Gradle构建工具
gradle文件的作用
工程与模块下都有自己的gradle文件,需要了解他们的作用;
项目:
settings.gradle 记录那些module应该被加入到编译过程;
build.gradle 配置会被应用到所有的项目中间
Module:
build.gradle 当前modlue的配置,如果与项目的build.gradle重复,优先级比项目的build.gradle高;
Gradle配置项解释
miniSdkVersion: 最小API level,兼容老版本手机系统就需要调小一点;
compileSdkVersion: 编译的SDK版本,默认选择最新的;
targetSdkVersion: 目标版本,
dependencies: 依赖配置,依赖的库
常见Gradle编译错误及解决方案
- 当前项目不支持这个gradle版本 原因:AndroidStudio版本高,Gradle版本低 解决方案:将项目的build.gradle改成电脑中已有的Gradle版本;
- Gradle无法下载更新
解决方案:修改Module的build.gradle
2. 中文乱码问题
当我们从远程仓库拉取的项目代码,使用AndroidStudio打开时可能会出现乱码,这一般是编码格式不一致导致的。一般将GBK编码或者GB2312与utf-8编码切换一下就能解决问题。
修改编码主要从四个地方修改:
- File Encoding(Global Encoding 和 Project Encoding)
- IDE Encoding
- Project Encoding
- File or Director Encoding 和 Property File Encoding
3. Android Studio快捷键(Mac)
撤销ctrl + z 反撤销 ctrl + shift + z
格式化代码:cmd + option + L
代码自动修正:option + shift + cmd
全局查找: cmd + shift + f
将局部变量设置为全局变量:cmd+option+f
提取常量:cmd+option+c
根据文件名创建文件:option+enter (用于在setContentView直接写入布局文件名时,通过此快捷键生成布局xml)
移动内部类:F6
快速写一个for循环:fori
快速工具栏:Option+Shift+A
从光标变为选中状态:Option + ↑
为当前语句添加条件判断Cmd + Option + T
多功能查找Cmd + o
选择抽象类的方法Ctrl + o
移动方法的上下顺序:Cmd + Shift + ↑或↓
二、 认识Activity
本节简单介绍一下Activity(活动),作为Android四大组件之一,作为学习Android开发,创建的第一个HelloWorld程序就会接触到Activity。
我们可以理解成Activity作为一个应用程序组件,它在屏幕上提供了一个区域,允许用户在上面做一些交互性的操作。可以将Activity理解成绘制用户界面的窗口,这个窗口可以填满整个屏幕或者浮动在其他窗口上方。
MainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// R文件为每一个资源文件按类别设置一个十六进制的索引,
// 它是一个final型的静态内部类,可以通过R.类名.资源名去操作对应的资源
setContentView(R.layout.activity_main);
}
}
为什么应用启动能直接打开MainActivity是因为AndroidManifest.xml中设置了对应Activity的intent-filter,当我们创建好了Activity后,AS会在清单文件中自动创建对应的配置信息;
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<!-- 启动入口只有一个-->
<action android:name="android.intent.action.MAIN" />
<!--为了在应用列表中设置启动图标-->
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
三、UI基础控件
View是Android所有UI组件的父类,TextView、Button、ImageView、EditText、ProgressBar
1. 通用属性
如果遇到Button的背景颜色无法更改的情况,实际上是系统使用了Material主题,我们只需将Button组件改为android.widget.Button即可
2. TextView
TextView的继承关系
TextView类似Swing中的JLabel,支持长文本、支持HTML
textSize设置字体大小,单位为sp;
设置行间距:android:lineSpacingExtra="20sp"
设置行倍距:android:lineSpacingMultiplier="2"
如果长文本内容太多,可以套一个ScrowView,但是注意一个ScrowView只能有一个子控件,若硬要多加几个控件,则需要再ScrowView中加一个布局;
3. EditText
设置输入文本的类型:android:inputType
设置提醒性文字:android:hint
设置文本输入监听可以使用addTextChangedListener,传入一个TextWatcher可以在文字改变前中后时机触发;
4. Button
监听器是一个对象,用户捕获View的状态
注册点击事件的方法:
自定义内部类
匿名内部类
当前Activity去实现事件接口
XML中直接绑定
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="布局文件中添加事件属性"
android:onClick="myClick" />
注意:在给多个组价绑定同一个方法时,如果使用swich语句根据点击的View来动态执行对应的方法时,系统会报错“Resource IDs will be non-final by default in Android Gradle Plugin version 8.0, avoid using them in switch case statements”
原因是在Android Gradle插件8.0后,资源标识符不再是final类型,因此不要在switch语句中使用,建议将资源ID赋值给静态常量,然后使用if-else if -else语句来操作;
public static final int FRAME = R.id.frame_layout;
public static final int TABLE = R.id.table_layout;
public static final int GRID = R.id.grid_layout;
public static final int CONSTRAINT = R.id.constraint_layout;
public void myClick(View v){
int resourceID = v.getId();
if(resourceID == FRAME){
Toast.makeText(this,"帧布局",Toast.LENGTH_SHORT).show();
}else if (resourceID == TABLE){
Toast.makeText(this,"表格布局",Toast.LENGTH_SHORT).show();
}else if (resourceID == GRID){
Toast.makeText(this,"网格布局",Toast.LENGTH_SHORT).show();
}else if(resourceID == CONSTRAINT){
Toast.makeText(this,"约束布局",Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this,"发生了错误",Toast.LENGTH_SHORT).show();
}
}
5. ImageView
用来显示可控制图像的控件,可以对其放大、缩小、旋转等操作。常用的属性有:
- android:src 指定前景图片资源
- android:background 指定背景图片资源
6. ProcessBar
进度条,默认情况下是圆形没有刻度,通过设置style可以设置水平进度条
style="?android:attr/progressBarStyleHorizontal" 设置进度条为水平进度条
android:max="200" 设置进度条最大值为200
android:progress="80" 设置进度条当前值
android:indeterminate="true" 设置进度条不确定终止时间的滚动
public class ProgressActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_progress);
ProgressBar progressBar = findViewById(R.id.progress);
// 创建一个线程,重写run方法,设置进度条进度
new Thread(){
@Override
public void run(){
for (int i = 0; i < 100; i++){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
progressBar.setProgress(i);
}
}
}.start();
}
}
自Android4.0以后,是不允许在线程中操作控件的,但是进度条Progress是一个特例;
7. Toast
无焦点提示,需要传入三个参数,环境上下文、提示性文本、持续时间
// this表示当前类
Toast.makeText(this,"姓名或者密码不能为空",Toast.LENGTH_SHORT).show();
四、布局
1.LinearLayout
线性布局重要属性
- android:layout_width 宽度
- android:layout_height 高度
- android:orientation 方向(vertical垂直 ,horizontal水平)
- android:layout_weight 权重(如果只给其中一个组件设置该属性,则该组件占据剩下的所有空间;如果需要按比例划分空间,则对应的长度或者宽度需要设置为0dp)
- android:layut_gravity 重力(设置当前控件相对于外层父容器的摆放重力)
2.RelativeLayout
依照参照物定位的布局,最灵活的布局;
相对布局的重要属性
- 相对于父容器(取值true/false)
- android:layout_alignParentRight
- Android:layout_centerHorizontal
- 如果需要完全居中,则可以使用android:layout_centerInParent="true"
- 相对于其他控件(取值控件id)
- android:layout_toRightOf
- android:layout_alignRight和 和控件的某个边线对齐
在相对布局下,控件具有默认向左向上靠的特性。
3.Framelayout
帧布局的重要属性:
- android:layout_gravity (控件重力),若不设置重力默认靠近左上角;
- android:foreground(前景)
- android:foregroundGravity(前景重力属性)
帧布局会按照控件的文本顺序,写在后面控件显示在最上面的一帧;
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="@mipmap/ic_launcher_round"
android:foregroundGravity="bottom|right">
<TextView
android:layout_width="400dp"
android:layout_height="400dp"
android:background="#ff0000"
android:layout_gravity="center"
android:text="帧布局"/>
<TextView
android:layout_width="300dp"
android:layout_height="300dp"
android:background="#00ff00"
android:layout_gravity="center"
android:text="帧布局"/>
<TextView
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#0000ff"
android:layout_gravity="center"
android:text="帧布局"/>
<TextView
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#ffff00"
android:layout_gravity="center"
android:text="帧布局"/>
<TextView
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#00ffff"
android:layout_gravity="center"
android:text="帧布局"/>
</FrameLayout>
4.TableLayout
表格布局的重要属性:
- android:stretchColumns 可以伸展的列,传入的数据是对应列的索引;
- android:shrinkColumns 可以收缩的列
- android:collapseColumns 可以隐藏的列
如果直接在TableLayout中添加控件,那么控件会和父容器等宽;如果要让控件显示在同一行,那么控件外层要加一对<TabelRow>标签;在<TabelRow>控件中,宽度都是默认wrap_content
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:stretchColumns="*">
<EditText
android:layout_marginTop="30dp"
android:text="" />
<TableRow>
<Button android:text="7" />
<Button android:text="8" />
<Button android:text="9" />
<Button android:text="/" />
</TableRow>
<TableRow>
<Button android:text="4" />
<Button android:text="5" />
<Button android:text="6" />
<Button android:text="x" />
</TableRow>
<TableRow>
<Button android:text="1" />
<Button android:text="2" />
<Button android:text="3" />
<Button android:text="-" />
</TableRow>
<TableRow>
<Button android:text="*" />
<Button android:text="0" />
<Button android:text="#" />
<Button android:text="+" />
</TableRow>
<TableRow>
<Button android:text="e" />
<Button android:text="%" />
<Button android:text="." />
<Button android:text="=" />
</TableRow>
<Button android:text="Clear" />
</TableLayout>
5.GridLayout
网格布局的重要属性
网格布局是Android4.0后出现的布局,可以定义多少行多少列;
- android:rowCount 定义行的数量
- android:columnCount 定义列的数量
- android:layout_row 位于第几行
- android:layout_rowSpan 跨几行
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_horizontal"
android:rowCount="5"
android:columnCount="4"
>
<Button android:text="7"/>
<Button android:text="8"/>
<Button android:text="9"/>
<Button android:text="/"/>
<Button android:text="4"/>
<Button android:text="5"/>
<Button android:text="6"/>
<Button android:text="x"/>
<Button android:text="1"/>
<Button android:text="2"/>
<Button android:text="3"/>
<Button android:text="-"/>
<Button android:text="*"/>
<Button android:text="0"/>
<Button android:text="#"/>
<Button android:text="+"/>
<Button android:text="0"
android:layout_columnSpan="2"
android:layout_gravity="fill"
/>
<Button android:text="."/>
<Button android:text="+"
android:layout_rowSpan="2"
android:layout_gravity="fill"
/>
<Button android:text="="
android:layout_columnSpan="3"
android:layout_gravity="fill"/>
</GridLayout>
6.ConstantLayout
重要属性:
app:layout_constraintBottom_toBottomOf 约束当前控件的底部去靠近别的控件的底部;
app:layout_constraintVertical_bias 垂直偏移量,数值范围0~1
Start等同于Left,End等同于Right
减少嵌套、扁平化
五、基础控件
Android官方文档:https://developer.android.com/reference
1. CheckBox
复选控件,继承自CompoundButton,本质上是一个Button
两种状态:
- setChecked() 设置是否被选中
- isChecked() 获取选中状态
- setOnCheckedChangeListener() 监听状态变化
给CheckBox设置一个监听:
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
Log.d(TAG, "onCheckedChanged: "+isChecked);
}
});
2. RadioButton
单选控件,和RadioGroup一起使用,一组中只能选择一个,无法通过点击变为未选中;
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
// 在这里处理选中的单选按钮变化
// checkedId 是被选中的单选按钮的 ID
}
});
3.ToggleButton
开关控件,
- android:textOn 开启时显示的文字
- android:textOff 关闭时显示的文字
- setChecked(boolean) 设置开关状态
ToogleButton设置监听用的方法和Button一样都是setOnClickListener;
获取开关是否被打开则使用isChecked()方法;
4. SeekBar
显示当前进度的控件
- getProgress() 获取进度
- setProgress() 读取进度
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// 这里不要做耗时操作,不然会阻塞主线程
Log.d(TAG, "onProgressChanged: " + progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// 仅仅在触摸开始的时候触发
Log.d(TAG, "onStartTrackingTouch: 开始"+ seekBar.getProgress());
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// 仅仅在触摸结束的时候触发
Log.d(TAG, "onStopTrackingTouch: 结束"+ seekBar.getProgress());
}
});
六、选餐UI综合案例
项目类教程学习方法
先看视频,看完后关闭视频,自己实现一遍;不会的再查视频,培养自己独立解决问题的能力;
对比源码找到优缺点,调整优化 。
从项目搭建开始接口设计模块实现再自己做一遍
1. 需求分析
功能需求:
- 输入姓名(EditText)、性别(RadioButton)、喜好(CheckBox)、预算(SeekBar);
- 点击寻找菜品按钮就可以根据喜好与预算寻找被筛选后菜品;
- 给显示信息按钮设置监听,点击功能有:通过ImageView显示菜品照片,以及显示下一份菜。
能力需求:
熟练使用Java面向对象思想、集合框架;
熟练使用Android 基础UI控件;
2. 布局设计
主要的控件先垂直线性布局,再水平线性布局;
3. 逻辑设计
主要分为四个模块来实现:
控件初始化:
定义一个findViews(),将所有的控件对象封装起来;
private void findViews() {
mNameEditText = findViewById(R.id.nameEditText);
mSexRadioGroup = findViewById(R.id.sexRadioGroup);
mSpicyCheckBox = findViewById(R.id.spicyCheckBox);
mSeaCheckBox = findViewById(R.id.seaCheckBox);
mSourCheckBox = findViewById(R.id.sourCheckBox);
mBudgetSeekBar = findViewById(R.id.budgetSeekBar);
mSearchButton = findViewById(R.id.searchButton);
mFoodImageView = findViewById(R.id.foodImageView);
mShowToggleButton = findViewById(R.id.showToggleButton);
}
再给每个对象做全局私有变量声明:
private EditText mNameEditText;
private RadioGroup mSexRadioGroup;
private CheckBox mSpicyCheckBox,mSeaCheckBox,mSourCheckBox;
private SeekBar mBudgetSeekBar;
private Button mSearchButton;
private ImageView mFoodImageView;
private ToggleButton mShowToggleButton;
数据初始化:
由于暂未使用数据库或者网络服务,先将菜品图片文件存储在工程项目目录drawable目录下,
创建一个model包,定义类Food.java和Person.java两个类,为其设计成员变量、构造方法、get、set方法;
使用ArrayList创建一个空的菜品列表mFoods
private void initData() {
// 创建一个空的菜品列表
mFoods = new ArrayList<>();
mFoods.add(new Food("麻辣香锅", 55, R.drawable.malaxiangguo, true, false, false));
mFoods.add(new Food("水煮鱼", 48, R.drawable.shuizhuyu, true, true, false));
mFoods.add(new Food("麻辣火锅", 80, R.drawable.malahuoguo, true, true, false));
mFoods.add(new Food("清蒸鲈鱼", 68, R.drawable.qingzhengluyu, false, true, false));
mFoods.add(new Food("桂林米粉", 15, R.drawable.guilin, false, false, false));
mFoods.add(new Food("上汤娃娃菜", 28, R.drawable.wawacai, false, false, false));
mFoods.add(new Food("红烧肉", 60, R.drawable.hongshaorou, false, false, false));
mFoods.add(new Food("木须肉", 40, R.drawable.muxurou, false, false, false));
mFoods.add(new Food("酸菜牛肉面", 35, R.drawable.suncainiuroumian, false, false, true));
mFoods.add(new Food("西芹炒百合", 38, R.drawable.xiqin, false, false, false));
mFoods.add(new Food("酸辣汤", 40, R.drawable.suanlatang, true, false, true));
// 创建一个用户
mPerson = new Person();
// 创建一个菜单列表
mMealList = new ArrayList<Food>();
}
踩坑记录:在创建菜单列表时,使用cmd+option+f将mMealList列表对象转变全局变量时,不小心将列表类型设置为Object类型,导致后面的菜品对象无法调用getPic方法;
控件设置监听
给姓名EditText、性别RadioButton设置监听后都将获取到的数据通过set方法赋值给Person类;
对于爱好CheckBox以及预算的SeekBar设置监听后直接将获取到的数据设置为当前MainActivity的全局变量;
private void setListener() {
// 姓名
mNameEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
if (mNameEditText != null) {
mPerson.setName(mNameEditText.getText().toString());
}
}
});
// 性别
mSexRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
if (i == R.id.male) {
mPerson.setSex("男");
} else if (i == R.id.female) {
mPerson.setSex("女");
} else {
mPerson.setSex("");
}
}
});
// 口味喜好
mSpicyCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
mIsSpicy = isChecked;
}
});
mSeaCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
mIsSeaFood = isChecked;
}
});
mSourCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
mIsSour = isChecked;
}
});
// 预算
mBudgetSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
budget = seekBar.getProgress();
Toast.makeText(MainActivity.this, "您的预算是:" + budget, Toast.LENGTH_SHORT).show();
}
});
// 寻找菜品
mSearchButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
search();
}
});
// 显示菜品信息
mShowToggleButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mShowToggleButton.isChecked()) {
mCurrentShowMealIndex++;
if (mCurrentShowMealIndex < mMealList.size()) {
mFoodImageView.setImageResource(mMealList.get(mCurrentShowMealIndex).getPic());
}
} else {
if (mCurrentShowMealIndex < mMealList.size()) {
String FoodName = "菜名:" + mMealList.get(mCurrentShowMealIndex).getName();
String UserInfo = ",姓名:" + mPerson.getName() + "," + mPerson.getSex();
Toast.makeText(MainActivity.this,
FoodName + UserInfo,
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this,
"没有啦", Toast.LENGTH_SHORT).show();
}
}
}
});
}
查找符合条件的菜品
private void search() {
if (mMealList == null) {
mMealList = new ArrayList<>();
}
// 清空菜单列表
mMealList.clear();
// 定义一个当前显示的菜品索引
mCurrentShowMealIndex = 0;
// 根据用户的条件过滤有效菜品清单
for (int index = 0; index < mFoods.size(); index++) {
Food currentMeal = mFoods.get(index);
if (currentMeal != null) {
if (currentMeal.getPrice() < budget &&
(currentMeal.isSpicy() == mIsSpicy ||
currentMeal.isSeaFood() == mIsSeaFood ||
currentMeal.isSour() == mIsSour)) {
mMealList.add(currentMeal);
}
}
}
// 立即显示搜索结果
if (mCurrentShowMealIndex < mMealList.size()) {
//todo 这里如何实现获取符合条件的菜品mMealList的第一份菜的id?
// 问题已经解决:mMealList在使用快捷键将局部变量设置为全局变量时,
// 将类设置成了Object类,导致无法调用get方法
mFoodImageView.setImageResource(mMealList.get(mCurrentShowMealIndex).getPic());
} else {
mFoodImageView.setImageResource(R.drawable.ic_launcher_foreground);
}
Toast.makeText(this, "符合条件的菜品数量为:" + mMealList.size() + "种", Toast.LENGTH_SHORT).show();
}
效果演示:
本文案例项目源码地址:
https://gitee.com/yushengtan/meal-selection/tree/logic/
相关推荐
- 自己动手写Android数据库框架_android开发数据库搭建
-
http://blog.csdn.net/feiduclear_up/article/details/50557590推荐理由关于Android数据库操作,由于每次都要自己写数据库操作,每次还得去...
- 谷歌开源大模型评测工具LMEval,打通谷歌、OpenAI、Anthropic
-
智东西编译|金碧辉编辑|程茜智东西5月28日消息,据科技媒体TheDecoder5月26日报道,当天,谷歌正式发布开源大模型评测框架LMEval,支持对GPT-4o、Claude3.7...
- 工信部:着力推动大模型算法、框架等基础性原创性的技术突破
-
工信部新闻发言人今日在发布会上表示,下一步,我们将坚持突出重点领域,大力推动制造业数字化转型,推动人工智能创新应用。主要从以下四个方面着力。一是夯实人工智能技术底座。通过科技创新重大项目,着力推动大模...
- 乒乓反复纠结“框架不稳定”的三个小误区
-
很多球友由于对框架的认知不清晰,往往会把“框架不稳定”当成一种心理负担,从而影响学球进度,其典型状态就是训练中有模有样,一旦进入实战,就像被捆住了手脚。通过训练和学习,结合“基本功打卡群”球友们交流发...
- 前AMD、英特尔显卡架构师Raja再战GPU,号称要全面重构堆栈
-
IT之家8月5日消息,知名GPU架构师拉贾科杜里(RajaKoduri)此前曾先后在AMD和英特尔的显卡部门担任要职。而在今日,由Raja创立的GPU软件与IP初创企...
- 三种必须掌握的嵌入式开发程序架构
-
前言在嵌入式软件开发,包括单片机开发中,软件架构对于开发人员是一个必须认真考虑的问题。软件架构对于系统整体的稳定性和可靠性是非常重要的,一个合适的软件架构不仅结构清晰,并且便于开发。我相...
- 怪不得别人3秒就知道软考案例怎么做能50+
-
软考高级统一合格标准必须三科都达到45分,案例分析也一直是考生头疼的一门,但是掌握到得分点,案例能不能50+还不是你们说了算吗?今天就结合架构案例考点,分享实用的备考攻略~一、吃透考点,搭建知识框架从...
- UML统一建模常用图有哪些,各自的作用是什么?一篇文章彻底讲透
-
10万+爆款解析:9大UML图实战案例,小白也能秒懂!为什么需要UML?UML(统一建模语言)是软件开发的“蓝图”,用图形化语言描述系统结构、行为和交互,让复杂需求一目了然。它能:降低沟通成本避...
- 勒索软件转向云原生架构,直指备份基础设施
-
勒索软件组织和其他网络犯罪分子正越来越多地将目标对准基于云的备份系统,对久已确立的灾难恢复方法构成了挑战。谷歌安全研究人员在一份关于云安全威胁演变的报告中警告称,随着攻击者不断改进数据窃取、身份泄露和...
- ConceptDraw DIAGRAM:释放创意,绘就高效办公新未来
-
在当今数字化时代,可视化工具已成为提升工作效率和激发创意的关键。ConceptDrawDIAGRAM,作为一款世界顶级的商业绘图软件,凭借其强大的功能和用户友好的界面,正逐渐成为众多专业人士的首选绘...
- APP 制作界面设计教程:一步到位_app界面设计模板一套
-
想让APP界面设计高效落地,无需繁琐流程,掌握“框架搭建—细节填充—体验优化”三步法,即可一步到位完成专业级设计。黄金框架搭建是基础。采用“三三制布局”:将屏幕横向三等分,纵向保留三...
- MCP 的工作原理:关键组件_mcp部件
-
以下是MCP架构的关键组件:MCP主机:像ClaudeDesktop、GitHubCopilot或旅行助手这样的AI智能体,它们希望通过MCP协议访问工具、资源等。MCP主机会...
- 软件架构_软件架构师工资一般多少
-
软件架构师自身需要是程序员,并且必须一直坚持做一线程序员。软件架构应该是能力最强的一群程序员,他们通常会在自身承接编程任务的同时,逐渐引导整个团队向一个能够最大化生产力的系统设计方向前进。软件系统的架...
- 不知不觉将手机字体调大!老花眼是因为“老了吗”?
-
现在不管是联系、交友,还是购物,都离不开手机。中老年人使用手机的时间也在逐渐加长,刷抖音、看短视频、发朋友圈……看手机的同时,人们也不得不面对“视力危机”——老花眼,习惯眯眼看、凑近看、瞪眼看,不少人...
- 8000通用汉字学习系列讲座(第046讲)
-
[表声母字]加(续)[从声汉字]伽茄泇迦枷痂袈笳嘉驾架咖贺瘸(计14字)嘉[正音]标准音读jiā。[辨形]上下结构,十四画。会意形声字,从壴从加,加也表声。注:从壴,字义与鼓乐有关;从加,字义与...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- mfc框架 (52)
- abb框架断路器 (48)
- beego框架 (52)
- java框架spring (58)
- grpc框架 (65)
- tornado框架 (48)
- 前端框架bootstrap (54)
- orm框架有哪些 (51)
- 知识框架图 (52)
- ppt框架 (55)
- 框架图模板 (59)
- 内联框架 (52)
- cad怎么画框架 (58)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)