private String location;//地区/城市名称
private String parent_city;//该地区/城市的上级城市
private String admin_area;//该地区/城市所属行政区域
private String cnty;//该地区/城市所属国家名称
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getParent_city() {
return parent_city;
}
public void setParent_city(String parent_city) {
this.parent_city = parent_city;
}
public String getAdmin_area() {
return admin_area;
}
public void setAdmin_area(String admin_area) {
this.admin_area = admin_area;
}
public String getCnty() {
return cnty;
}
public void setCnty(String cnty) {
this.cnty = cnty;
}
}
然后在litepal.xml中增加一个mapping
最后在WeatherApplication中的onCreate方法中初始化,初始化的时候,你的数据库就创建好了,数据库名称是GoodWeather,表名是ResidentCity
那么这一块的内容就写完了,只需要在实际应用中结合业务逻辑使用就可以了,当然你也可以去自己尝试一下,感兴趣的可以看Android LitePal的简单使用这篇文章。
③ 布局item
通过最上面的效果图可以看到是两个列表,其中一个是已经添加的城市列表,另一个是搜索出来的城市列表,既然两个列表就要有两个item,当然你也可以用一个item来写,只不过用的时候要多写一些代码,首先当然是从布局开始着手了。
在app中res下的layout中创建两个布局文件
item_commonly_city_list.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout android:orientation=“vertical”
xmlns:android=“http://schemas.android.com/apk/res/android”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”>
<com.mcxtzhang.swipemenulib.SwipeMenuLayout
xmlns:android=“http://schemas.android.com/apk/res/android”
android:layout_width=“match_parent”
android:layout_height=“@dimen/dp_50”
android:clickable=“true”
android:paddingBottom=“1dp”>
<TextView
android:id=“@+id/tv_city_name”
android:gravity=“center_vertical”
android:paddingLeft=“@dimen/dp_16”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:textColor=“@color/shallow_black”
android:background=“?android:attr/selectableItemBackground”
android:text=“城市”/>
<Button
android:id=“@+id/btn_delete”
android:layout_width=“@dimen/dp_100”
android:layout_height=“match_parent”
android:background=“@color/red”
android:text=“删除”
android:textColor=“@android:color/white”/>
</com.mcxtzhang.swipemenulib.SwipeMenuLayout>
<View
android:background=“@color/line_gray”
android:layout_width=“match_parent”
android:layout_height=“@dimen/dp_1”/>
item_commonly_city_add_list.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
android:layout_width=“match_parent”
android:id=“@+id/item_add_city”
android:background=“?android:attr/selectableItemBackground”
android:layout_height=“wrap_content”
android:orientation=“vertical”>
<TextView
android:id=“@+id/tv_location”
android:gravity=“center_vertical”
android:layout_width=“match_parent”
android:textSize=“@dimen/sp_16”
android:paddingLeft=“@dimen/dp_16”
android:layout_height=“@dimen/dp_50”
android:textColor=“@color/shallow_black” />
<View
android:layout_width=“match_parent”
android:layout_height=“@dimen/dp_1”
android:background=“@color/line_gray” />
④ 列表适配器
然后创建适配器
CommonlyCityAdapter.java
package com.llw.goodweather.adapter;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.llw.goodweather.R;
import com.llw.mvplibrary.bean.ResidentCity;
import java.util.List;
/**
- 常用城市列表适配器
*/
public class CommonlyCityAdapter extends BaseQuickAdapter<ResidentCity, BaseViewHolder> {
public CommonlyCityAdapter(int layoutResId, @Nullable List data) {
super(layoutResId, data);
}
@Override
protected void convert(BaseViewHolder helper, ResidentCity item) {
helper.setText(R.id.tv_city_name, item.getLocation());
//添加点击事件
helper.addOnClickListener(R.id.tv_city_name)
.addOnClickListener(R.id.btn_delete);
}
}
CommonlyCityAddAdapter.java
package com.llw.goodweather.adapter;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.llw.goodweather.R;
import com.llw.goodweather.bean.SearchCityResponse;
import java.util.List;
import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
/**
- 添加城市时搜索返回结果列表适配器
*/
public class CommonlyCityAddAdapter extends BaseQuickAdapter<SearchCityResponse.HeWeather6Bean.BasicBean, BaseViewHolder> {
private String edStr;//关键字
public CommonlyCityAddAdapter(int layoutResId, @Nullable List<SearchCityResponse.HeWeather6Bean.BasicBean> data) {
super(layoutResId, data);
}
@Override
protected void convert(BaseViewHolder helper, SearchCityResponse.HeWeather6Bean.BasicBean item) {
TextView textView = helper.getView(R.id.tv_location);
String result = item.getLocation() + " , " + item.getParent_city() + " , " + item.getAdmin_area() + " , " + item.getCnty();
if (edStr != null && edStr.length() > 0) {
textView.setText(matcherSearchText(mContext.getResources().getColor(R.color.shallow_yellow),result,edStr));
} else {
textView.setText(item.getLocation() + " , " +
item.getParent_city() + " , " +
item.getAdmin_area() + " , " +
item.getCnty());
}
helper.addOnClickListener(R.id.item_add_city);
}
/**
-
改变颜色
-
@param str 输入的文本
*/
public void changTxColor(String str) {
edStr = str;
notifyDataSetChanged();
}
/**
-
改变一段文本中第一个关键字的文字颜色
-
@param color 要改变文字的颜色
-
@param string 文本字符串
-
@param keyWord 关键字
-
@return
*/
public static CharSequence matcherSearchText(int color, String string, String keyWord) {
SpannableStringBuilder builder = new SpannableStringBuilder(string);
int indexOf = string.indexOf(keyWord);
if (indexOf != -1) {
builder.setSpan(new ForegroundColorSpan(color), indexOf, indexOf + keyWord.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
}
return builder;
}
}
适配器的代码都是比较简单的,其中matcherSearchText方法是根据传入的关键字找到它在一段字符串中的第一次出现的位置,并修改字体颜色。
⑤ 代码整合
打开CommonlyUsedCityActivity.java
然后会出现五个构造方法,分别是
//数据初始化
@Override
public void initData(Bundle savedInstanceState) {
}
@Override
public int getLayoutId() {
return R.layout.activity_commonly_used_city;
}
@Override
protected SearchCityContract.SearchCityPresenter createPresent() {
return new SearchCityContract.SearchCityPresenter();
}
/**
-
请求数据返回处理
-
@param response
*/
@Override
public void getSearchCityResult(Response response) {
}
/**
- 网络异常返回处理
*/
@Override
public void getDataFailed() {
dismissLoadingDialog();//关闭弹窗
ToastUtils.showShortToast(context, “网络异常”);//这里的context是框架中封装好的,等同于this
}
现在你可以把onCreate方法删掉了。
首先初始化控件
@BindView(R.id.edit_query)
EditText editQuery;//输入框
@BindView(R.id.iv_clear_search)
ImageView ivClearSearch;//清除输入框内容的图标
@BindView(R.id.toolbar)
Toolbar toolbar;//标题控件
@BindView(R.id.rv_commonly_used)
RecyclerView rvCommonlyUsed;//常用城市列表
@BindView(R.id.rv_search)
RecyclerView rvSearch;//搜索城市列表
@BindView(R.id.lay_normal)
LinearLayout layNormal;//常用城市为空时展示的布局
CommonlyCityAdapter mAdapter;//常用城市列表适配器
List<SearchCityResponse.HeWeather6Bean.BasicBean> mList = new ArrayList<>();//数据源
CommonlyCityAddAdapter mAdapterAdd;//搜索城市列表适配器
List cityList;//常用城市列表
根据常用城市数据来进行页面控件显示/隐藏
/**
- 根据常用城市数据来进行页面控件显示/隐藏
*/
private void initHideOrShow() {
ivClearSearch.setVisibility(View.GONE);//隐藏清除输入框内容的图标
rvSearch.setVisibility(View.GONE);//隐藏搜索结果列表
if (cityList != null && cityList.size() > 0) {//有数据
rvCommonlyUsed.setVisibility(View.VISIBLE);//显示常用城市列表
layNormal.setVisibility(View.GONE);//隐藏没有数据时的布局
} else {//没数据
rvCommonlyUsed.setVisibility(View.GONE);//隐藏常用城市列表
layNormal.setVisibility(View.VISIBLE);//显示没有数据时的布局
}
}
初始化常用城市列表数据
这个方法主要是查询表中的所有数据,有数据就渲染出来,没有数据就更换为相应的表示布局,其中对item中的点击事件做了处理,分别item的点击和侧滑菜单的点击。
/**
- 初始化常用城市列表数据
*/
private void initCityList() {
//查询ResidentCity表中所有数据
cityList = LitePal.findAll(ResidentCity.class);
if (cityList.size() > 0 && cityList != null) {
mAdapter = new CommonlyCityAdapter(R.layout.item_commonly_city_list, cityList);
rvCommonlyUsed.setLayoutManager(new LinearLayoutManager(context));
rvCommonlyUsed.setAdapter(mAdapter);
mAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
@Override
public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
switch (view.getId()) {
case R.id.tv_city_name:
SPUtils.putString(Constant.LOCATION, cityList.get(position).getLocation(), context);
//发送消息
EventBus.getDefault().post(new SearchCityEvent(cityList.get(position).getLocation(),
cityList.get(position).getParent_city()));
finish();
break;
case R.id.btn_delete://删除
LitePal.delete(ResidentCity.class, cityList.get(position).getId());//删除指定id
initCityList();
//删除数据后判断一下显示和隐藏的控件
initHideOrShow();
break;
}
}
});
mAdapter.notifyDataSetChanged();
} else {
rvCommonlyUsed.setVisibility(View.GONE);
layNormal.setVisibility(View.VISIBLE);
}
}
添加城市列表item,点击保存数据并发送事件
/**
-
添加城市列表item,点击保存数据并发送事件
-
@param position
*/
private void QueryWeather(int position) {
ResidentCity residentCity = new ResidentCity();
residentCity.setLocation(mList.get(position).getLocation());//地区/城市名称
residentCity.setParent_city(mList.get(position).getParent_city());//该地区/城市的上级城市
residentCity.setAdmin_area(mList.get(position).getAdmin_area());//该地区/城市所属行政区域
residentCity.setCnty(mList.get(position).getCnty());//该地区/城市所属国家名称
residentCity.save();//保存数据到数据库中
if (residentCity.save()) {//保存成功
//然后使用之前在搜索城市天气中写好的代码
SPUtils.putString(Constant.LOCATION, mList.get(position).getLocation(), context);
//发送消息
EventBus.getDefault().post(new SearchCityEvent(mList.get(position).getLocation(),
mList.get(position).getParent_city()));
finish();
} else {//保存失败
ToastUtils.showShortToast(context, “添加城市失败”);
}
}
初始化搜索要添加的城市列表
/**
- 初始化搜索要添加的城市列表
*/
private void initQueryAddList() {
mAdapterAdd = new CommonlyCityAddAdapter(R.layout.item_commonly_city_add_list, mList);
rvSearch.setLayoutManager(new LinearLayoutManager(context));
rvSearch.setAdapter(mAdapterAdd);
//点击item时保存到数据库中,同时传递数据到主页面查询出天气
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)
![](https://img-blog.csdnimg.cn/img_convert/ec2dfb00d2770dcb6f9d123159fe7ac2.jpeg)
文末
初级工程师拿到需求会直接开始做,然后做着做着发现有问题了,要么技术实现不了,要么逻辑有问题。
而高级工程师拿到需求会考虑很多,技术的可行性?对现有业务有没有帮助?对现有技术架构的影响?扩展性如何?等等…之后才会再进行设计编码阶段。
而现在随着跨平台开发,混合式开发,前端开发之类的热门,Android开发者需要学习和掌握的技术也在不断的增加。
通过和一些行业里的朋友交流讨论,以及参考现在大厂面试的要求。我们花了差不多一个月时间整理出了这份Android高级工程师需要掌握的所有知识体系。你可以看下掌握了多少。
混合式开发,微信小程序。都是得学会并且熟练的
这些是Android相关技术的内核,还有Java进阶
高级进阶必备的一些技术。像移动开发架构项目实战等
Android前沿技术;包括了组件化,热升级和热修复,以及各种架构跟框架的详细技术体系
以上即是我们整理的Android高级工程师需要掌握的技术体系了。可能很多朋友觉得很多技术自己都会了,只是一些新的技术不清楚而已。应该没什么太大的问题。
而这恰恰是问题所在!为什么别人高级工程师能年限突破30万,而你只有十几万呢?
就因为你只需补充你自己认为需要的,但并不知道企业需要的。这个就特别容易造成差距。因为你的技术体系并不系统,是零碎的,散乱的。那么你凭什么突破30万年薪呢?
我这些话比较直接,可能会戳到一些人的玻璃心,但是我知道肯定会对一些人起到点醒的效果的。而但凡只要有人因为我的这份高级系统大纲以及这些话找到了方向,并且付出行动去提升自我,为了成功变得更加努力。那么我做的这些就都有了意义。
喜欢的话请帮忙转发点赞一下能让更多有需要的人看到吧。谢谢!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
响?扩展性如何?等等…之后才会再进行设计编码阶段。
而现在随着跨平台开发,混合式开发,前端开发之类的热门,Android开发者需要学习和掌握的技术也在不断的增加。
通过和一些行业里的朋友交流讨论,以及参考现在大厂面试的要求。我们花了差不多一个月时间整理出了这份Android高级工程师需要掌握的所有知识体系。你可以看下掌握了多少。
混合式开发,微信小程序。都是得学会并且熟练的
[外链图片转存中…(img-I7bdQGFo-1711547083305)]
这些是Android相关技术的内核,还有Java进阶
[外链图片转存中…(img-AhyGd90M-1711547083306)]
高级进阶必备的一些技术。像移动开发架构项目实战等
[外链图片转存中…(img-U643azh5-1711547083306)]
Android前沿技术;包括了组件化,热升级和热修复,以及各种架构跟框架的详细技术体系
[外链图片转存中…(img-ipdjr5fD-1711547083306)]
以上即是我们整理的Android高级工程师需要掌握的技术体系了。可能很多朋友觉得很多技术自己都会了,只是一些新的技术不清楚而已。应该没什么太大的问题。
而这恰恰是问题所在!为什么别人高级工程师能年限突破30万,而你只有十几万呢?
就因为你只需补充你自己认为需要的,但并不知道企业需要的。这个就特别容易造成差距。因为你的技术体系并不系统,是零碎的,散乱的。那么你凭什么突破30万年薪呢?
我这些话比较直接,可能会戳到一些人的玻璃心,但是我知道肯定会对一些人起到点醒的效果的。而但凡只要有人因为我的这份高级系统大纲以及这些话找到了方向,并且付出行动去提升自我,为了成功变得更加努力。那么我做的这些就都有了意义。