天气预报APP(2)
之前实现了能够罗列可以罗列出全国所有的省、市、县,然后就是查询全国任意城市的天气信息。查询天气信息使用的是和风天气的api,这个api获得的天气信息是JSON格式的。
使用GSON库解析JSON数据的第一步要先定义用于映照的类。
我对官方实例做了一下删减,然后可以看到这次我想要展示在这次这个项目中的信息:
{
"HeWeather5": [
{
"aqi": {
"city": {
"aqi": "46",
"pm25": "26",
}
},
"basic": {
"city": "秦皇岛",
"id": "CN101091101",
"update": {
"loc": "2017-09-10 14:46",
}
},
"daily_forecast": [
{
"cond": { "txt_d": "小雨",
},
"date": "2017-09-10",
"tmp": {
"max": "26",
"min": "17"
},
},
{ "cond": {
"txt_d": "晴",
},
"date": "2017-09-11", ,
"tmp": {
"max": "25",
"min": "12"
},
},
{
"cond": {
"txt_d": "晴",
},
"date": "2017-09-12",
"tmp": {
"max": "26",
"min": "15"
}, }
],
"status": "ok",
"suggestion": { "comf": {
"brf": "较舒适",
"txt": "白天有雨,从而使空气湿度加大,会使人们感觉有点儿闷热,但早晚的天气很凉爽、舒适。"
},
"cw": {
"brf": "不宜",
"txt": "不宜洗车,未来24小时内有雨,如果在此期间洗车,雨水和路上的泥水可能会再次弄脏您的爱车。"
}, "sport": {
"brf": "较不宜",
"txt": "有降水,推荐您在室内进行健身休闲运动;若坚持户外运动,须注意携带雨具并注意避雨防滑。"
},
}
}
]
}
天气信息总
其中天气情况AQI:
{
"aqi": {
"city": {
"aqi": "46",
"pm25": "26",
}
}
}
定义的AQI类代码为:
public class AQI { public AQIcity city; public class AQIcity{ public String aqi; public String pm25;
}
}
这里要说的就是“{}”包括一个类要用一个类去映照。
然后是城市的信息Basic:
{
"basic": {
"city": "秦皇岛",
"id": "CN101091101",
"update": {
"loc": "2017-09-10 14:46",
}
},
对应应该定义映照的java类:
public class Basic { @SerializedName("city")
public String cityName; @SerializedName("id")
public String weatherId; public Update update; public class Update{ @SerializedName("loc")
public String updateTime;
}
}
如果获得的数据的变量名设置自己不喜欢,可以用@SerializedName("loc")去映照,
然后是天气预测情况daily_forecast:
"daily_forecast": [
{
"cond": { "txt_d": "小雨",
},
"date": "2017-09-10",
"tmp": {
"max": "26",
"min": "17"
},
},
{ "cond": {
"txt_d": "晴",
},
"date": "2017-09-11", ,
"tmp": {
"max": "25",
"min": "12"
},
},
{
"cond": {
"txt_d": "晴",
},
"date": "2017-09-12",
"tmp": {
"max": "26",
"min": "15"
}, }
],
用“[]”包括的是数组,也就是说这个daily_forecast在建立映照的时候,应该也建立一个数组。不过这里先定义数组的成员:
public class Forecast { public String date; @SerializedName("tmp")
public Temperature temperature; @SerializedName("cond")
public More more; public class Temperature{ public String max; public String min;
} public class More{ @SerializedName("txt_d")
public String info; }
}
然后是其他就没什么特殊的了:
public class Now { @SerializedName("tmp")
public String temperature; @SerializedName("cond")
public More more; public class More{ @SerializedName("txt")
public String info;
} }
public class Suggestion { @SerializedName("comf")
public Comfort comfort; @SerializedName("cw")
public CarWash carWash; public Sport sport; public class Comfort { @SerializedName("txt")
public String info; } public class CarWash { @SerializedName("txt")
public String info; } public class Sport { @SerializedName("txt")
public String info; }
}
其他信息
最后要合在一起,因为对于整个天气信息来说,上面的都是用“{}”包括的一个类,所以:
public class Weather { public String status; public Basic basic; public AQI aqi; public Now now; public Suggestion suggestion; @SerializedName("daily_forecast")
public List<Forecast> forecastList;
}
对于[]数组就是在这里定义。
然后就是具体的解析代码:
public class Utility {
/**
* 将返回的JSON数据解析成Weather类
*/
public static Weather handleWeatherResponse(String response){
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray jsonArray = jsonObject.getJSONArray("HeWeather");
String weatherContent = jsonArray.getJSONObject(0).toString();
return new Gson().fromJson(weatherContent,Weather.class);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
这样就解析完毕了。
然后是界面的布局代码编写了,
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"> <ImageView
android:id="@+id/bing_pic_img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"/> <ScrollView
android:id="@+id/weather_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
android:overScrollMode="never"> <LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"> <include layout="@layout/title"/> <include layout="@layout/now"/> <include layout="@layout/forecast"/> <include layout="@layout/aqi"/> <include layout="@layout/suggestion"/>
</LinearLayout>
</ScrollView> </RelativeLayout>
这是整个活动布局,其中正文部分使用的是子项布局,因为内容比较多,这样显得条理一些。
layout/title:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"> <Button
android:id="@+id/nav_button"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginLeft="15dp"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:background="@drawable/ic_home"/> <TextView
android:id="@+id/title_city"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="#fff"
android:textSize="20sp"/> <TextView
android:id="@+id/title_update_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="15dp"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:textColor="#fff"
android:textSize="16sp"/> </RelativeLayout>
title
layout/now:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"> <TextView
android:id="@+id/degree_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:textColor="#fff"
android:textSize="60sp" /> <TextView
android:id="@+id/weather_info_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:textAlignment="textEnd"
android:textColor="#fff"
android:textSize="20sp" /> </LinearLayout>
now
layout/forecast:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="15dp"
android:background="#8000"> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="预报"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp"
android:textColor="#fff"
android:textSize="20sp"/> <LinearLayout
android:id="@+id/forecast_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
forecast
layout/forecast_item:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"> <TextView
android:id="@+id/data_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="2"
android:textColor="#fff" /> <TextView
android:id="@+id/info_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:textColor="#fff" /> <TextView
android:id="@+id/max_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="right"
android:textColor="#fff"/> <TextView
android:id="@+id/min_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="right"
android:textColor="#fff" />
</LinearLayout>
forcast_item
layout/aqi:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:background="#8000"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="空气质量"
android:textColor="#fff"
android:textSize="20sp"/> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"> <RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerVertical="true"> <TextView
android:id="@+id/aqi_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#fff"
android:textSize="40sp"/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="AQI指数"
android:textColor="#fff"/> </LinearLayout>
</RelativeLayout> <RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerVertical="true"> <TextView
android:id="@+id/pm25_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#fff"
android:textSize="40sp"/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="PM2.5指数"
android:textColor="#fff"/> </LinearLayout> </RelativeLayout> </LinearLayout> </LinearLayout>
aqi
layout/suggestion:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:background="#8000"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="生活建议"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp"
android:textColor="#fff"
android:textSize="20sp"/> <TextView
android:id="@+id/comfort_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:layout_margin="15dp"/> <TextView
android:id="@+id/car_wash_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#fff"
android:layout_margin="15dp"/> <TextView
android:id="@+id/sport_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#fff"
android:layout_margin="15dp" />
</LinearLayout>
suggestion
然后是活动的java代码:
public class WeatherActivity extends AppCompatActivity { public SwipeRefreshLayout swipeRefreshLayout; private ImageView bingPicImg; private ScrollView weatherLayout; private TextView titleCity; private TextView titleUpdateTime; private TextView degreeText; private TextView weatherInfoText; private LinearLayout forecastLayout; private TextView aqiText; private TextView pm25Text; private TextView comfortText; private TextView carWashText; private TextView sportText; public DrawerLayout drawerLayout; public Button navbutton; String weatherId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //使状态栏和背景图融合在一块
if(Build.VERSION.SDK_INT >= 21){
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);//设置为全屏模式
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
setContentView(R.layout.activity_weather); //初始化各个控件
weatherLayout = (ScrollView) findViewById(R.id.weather_layout);
titleCity = (TextView) findViewById(R.id.title_city);
titleUpdateTime = (TextView) findViewById(R.id.title_update_time);
degreeText = (TextView) findViewById(R.id.degree_text);
weatherInfoText = (TextView) findViewById(R.id.weather_info_text);
forecastLayout = (LinearLayout) findViewById(R.id.forecast_layout);
aqiText = (TextView) findViewById(R.id.aqi_text);
pm25Text = (TextView) findViewById(R.id.pm25_text);
comfortText = (TextView) findViewById(R.id.comfort_text);
carWashText = (TextView) findViewById(R.id.car_wash_text);
sportText = (TextView) findViewById(R.id.sport_text);
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
navbutton = (Button) findViewById(R.id.nav_button); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String weatherString = prefs.getString("weather",null);
if(weatherString != null){
//有缓存时直接解析天气数据
Weather weather = Utility.handleWeatherResponse(weatherString);
weatherId = weather.basic.weatherId;
showWeatherInfo(weather);
}else {
//无缓存时直接去服务器查询天气
weatherId = getIntent().getStringExtra("weather_id");
weatherLayout.setVisibility(View.INVISIBLE);
requestWeather(weatherId);
} //向下滑动刷新天气
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
swipeRefreshLayout.setColorSchemeResources(R.color.colorAccent);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener(){
@Override
public void onRefresh() {
requestWeather(weatherId);
}
}); //背景图片
bingPicImg = (ImageView) findViewById(R.id.bing_pic_img);
String bingpic = prefs.getString("bing_pic",null);
if(bingpic != null){
Glide.with(this).load(bingpic).into(bingPicImg);
}else {
loadBingPic();
} //顶部按钮打开侧边栏
navbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawerLayout.openDrawer(GravityCompat.START);
}
}); } /**
* 根据天气ID请求城市天气信息
*/
public void requestWeather(final String weatherId){
String weatherUrl = "http://guolin.tech/api/weather?cityid=" + weatherId +"&key=32d1c829ed7d483086f4f5b4d5947cef";
HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
final String responseText = response.body().string();
final Weather weather = Utility.handleWeatherResponse(responseText);
runOnUiThread(new Runnable() {
@Override
public void run() {
if(weather != null && "ok".equals(weather.status)){
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(WeatherActivity.this).edit();
editor.putString("weather", responseText);
editor.apply();
showWeatherInfo(weather);
Toast.makeText(WeatherActivity.this, "天气获取成功", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(WeatherActivity.this, "天气获取失败", Toast.LENGTH_SHORT).show();
}
swipeRefreshLayout.setRefreshing(false);//传入false表示刷新事件结束
}
});
} @Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(WeatherActivity.this, "天气获取失败", Toast.LENGTH_SHORT).show();
swipeRefreshLayout.setRefreshing(false);//传入false表示刷新事件结束
}
});
} });
} /**
* 处理展示Weather实体类中的数据
*/
private void showWeatherInfo(Weather weather){
String cityName = weather.basic.cityName;
String updateTime = weather.basic.update.updateTime.split(" ")[1];
String degree = weather.now.temperature + "℃";
String weatherInfo = weather.now.more.info;
titleCity.setText(cityName);
titleUpdateTime.setText(updateTime);
degreeText.setText(degree);
weatherInfoText.setText(weatherInfo);
forecastLayout.removeAllViews();
for(Forecast forecast: weather.forecastList){
View view = LayoutInflater.from(this).inflate(R.layout.forecast_item, forecastLayout, false);
TextView dataText = (TextView) view.findViewById(R.id.data_text);
TextView infoText = (TextView) view.findViewById(R.id.info_text);
TextView maxText = (TextView) view.findViewById(R.id.max_text);
TextView minText = (TextView) view.findViewById(R.id.min_text);
dataText.setText(forecast.date);
infoText.setText(forecast.more.info);
maxText.setText(forecast.temperature.max);
minText.setText(forecast.temperature.min);
forecastLayout.addView(view);
}
if(weather.aqi != null){
aqiText.setText(weather.aqi.city.aqi);
pm25Text.setText(weather.aqi.city.pm25);
} String comfort = "舒适度:" + weather.suggestion.comfort.info;
String carWash = "洗车指数:" + weather.suggestion.carWash.info;
String sport = "运动建议:" + weather.suggestion.sport.info; comfortText.setText(comfort);
carWashText.setText(carWash);
sportText.setText(sport);
weatherLayout.setVisibility(View.VISIBLE); } private void loadBingPic(){
String Url = "http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US";
HttpUtil.sendOkHttpRequest(Url, new Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
String responseText = response.body().string();
final Images images = Utility.handleImagesrResponse(responseText);
final String url = "http://s.cn.bing.net"+ images.url;
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
Glide.with(WeatherActivity.this).load(url).into(bingPicImg);
}
});
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(WeatherActivity.this, "图片获取失败", Toast.LENGTH_SHORT).show();
}
});
} });
}
}
WeatherActivity
这个活动实现的功能大概有:
1、向下滑动刷新:
布局代码这样编写。
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent"> </ScrollView...> </android.support.v4.widget.SwipeRefreshLayout>
活动中的JAVA代码:
public SwipeRefreshLayout swipeRefreshLayout;
//向下滑动刷新天气
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
swipeRefreshLayout.setColorSchemeResources(R.color.colorAccent);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener(){
@Override
public void onRefresh() {
requestWeather(weatherId);//从服务器获取天气信息
}
});
2、从必应api获得的每天一刷新的图片,使用Glide设置图片。
public class Images { public String url;
}
然后解析java代码:
public class Utility { public static Images handleImagesrResponse(String response){
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray jsonArray = jsonObject.getJSONArray("images");
String weatherContent = jsonArray.getJSONObject(0).toString();
return new Gson().fromJson(weatherContent,Images.class);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
活动中调用的代码:
private void loadBingPic(){
String Url = "http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US";
HttpUtil.sendOkHttpRequest(Url, new Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
String responseText = response.body().string();
final Images images = Utility.handleImagesrResponse(responseText);
final String url = "http://s.cn.bing.net"+ images.url;
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
Glide.with(WeatherActivity.this).load(url).into(bingPicImg);
}
});
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(WeatherActivity.this, "图片获取失败", Toast.LENGTH_SHORT).show();
}
});
} });
}
3、侧边栏切换城市:
布局:
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.widget.SwipeRefreshLayout...> <fragment
android:id="@+id/choose_area_fragment"
android:name="xbt.exp20.ChooseAreaFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start" />
</android.support.v4.widget.DrawerLayout>
之前的省市县列表作为侧边栏,
然后有一个按钮打开侧边栏:
//顶部按钮打开侧边栏
navbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawerLayout.openDrawer(GravityCompat.START);
}
});
这里打开侧边栏选中某个城市之后要自动把侧边栏关闭,以及刷新天气信息,所以需要修改碎片的列表点击响应:
//列表的点击事件响应
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
//如果当前级别是省,那点击选取的就是某个省,而想要查询的是选中省有那些城市,市同理 ,想要查询这个城市有那些县
if(currentLevel == LEVEL_PROVINCE){
selectedProvince = provinceList.get(position);
queryCities();//查询全国所有的省,优先从数据库查询,如果没有查到再去服务器上查询
}else if(currentLevel == LEVEL_CITY){
selectedCity = cityList.get(position);
queryCounties();//查询全国所有的省,优先从数据库查询,如果没有查到再去服务器上查询
}else if(currentLevel == LEVEL_COUNTY){
String weatherId = countyList.get(position).getWeatherId();
if(getActivity() instanceof MainActivity) {
Intent intent = new Intent(getActivity(), WeatherActivity.class);
intent.putExtra("weather_id", weatherId);
startActivity(intent);
getActivity().finish();
}else if(getActivity() instanceof WeatherActivity){
WeatherActivity activity = (WeatherActivity) getActivity();
activity.drawerLayout.closeDrawers();
activity.swipeRefreshLayout.setRefreshing(true);
activity.requestWeather(weatherId);
}
}
}
});
使用instanceof关键字判断一个对象是否属于某个类的实例,判断当时碎片处于那个活动中,并设置相应的响应。
基础的根据城市ID获取天气信息,并展示在活动上,以及将获取过的天气缓存下来就不在赘述了
项目截图:
最新文章
- 运维自动化工具---Puppet
- Visual Studio Code 1.0发布:100+语言,300+pull请求,1000+扩展
- js实现各种常用排序算法
- BI 商业智能理解结构图
- 用linux服务器下的/dev/shm/来释放磁盘的压力
- http://jingyan.baidu.com/article/a3761b2b66fe141577f9aa51.html
- (原创) mac 10.9.2 eclipse 的 CDT 的 异常的修复
- linux-FTP服务常用命令及测试
- python如何保证多个线程同时修改共享对象时不出错!
- awk 使用案例
- vue2 vue-router 组装
- linux_Nginx优化
- let和const
- Nodejs之路:异步I/O的过程
- MyBatis第一个案例的优化,通过映射文件与接口进行绑定
- asyncio的核心概念与基本架构
- Nodejs学习笔记:基础
- Git 的4个阶段的撤销更改
- python 的print和特殊方法 __str__和__repr__
- windows 下,CCXT库的安装
热门文章
- 开源FTP/SFTP客户端 FileZilla v3.31.0 绿色便携版
- SQL Server Update 链接修改和when的应用
- 基于SpringCloud的微服务架构实战案例项目
- centos 上安装redis 3.0.5
- Creating a Manager for Multiple Threads_翻译
- 微信小程序开发--组件(4)
- SpringBoot | 第三十八章:基于RabbitMQ实现消息延迟队列方案
- 关于页面scroolTop的获取
- 你真的了解 Cookie 和 Session 吗
- SQL Server 保存特殊字符时乱码