1. 前言
最近專案中需要做模糊搜索的功能,剛開始覺得很難,但仔細想想也沒什么,因為具體的模糊搜索部分是后端提供介面,而我們需要做的就是當搜索框內容發生變化時就執行一次搜索功能而已,
2. 效果圖
可以看到
- 文本框在輸入時實時進行搜索
- 當搜索沒有結果時,底部的結果展示直接隱藏掉
- 茅臺并不堅挺…
3. 思路
-
搜索框部分使用EditText,通過
addTextChangedListener方法來實作對其的監聽 -
介面部分,這里我使用百度的介面,簡單的通過Retrofit2來實作網路請求
-
模糊搜索結果展示部分,我使用Recyclerview來實作對模糊搜索結果的展示
4. 實作
4.1 EditText監聽部分
方法解釋:
EditText的addTextChangedListener監聽如下,可以看到共有三個方法
-
beforeTextChanged()在EditText輸入前,先呼叫一次該方法
-
afterTextChanged()在EditText輸入完成后,呼叫一次該方法
-
onTextChanged()在EditText輸入程序中,不斷的回呼該方法
etContent.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
})
效果實作:
我們想實作的效果有如下內容
- 當輸入框內有內容時則顯示洗掉按鈕,沒有內容時則隱藏
- 在輸入程序中不斷的進行網路請求
- 搜索有結果時則顯示Recyclerview,沒有資料則隱藏
具體實作:
etContent.addTextChangedListener(object : TextWatcher {
......
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (etContent.text.isNullOrEmpty()) {
//輸入框為空,洗掉按鈕隱藏
ivDel.visibility = View.GONE
//當輸入框為空時,隱藏recyclerview,目的是隱藏上一次的搜索結果
recy.visibility = View.GONE
} else {
//輸入框不為空,洗掉按鈕展示
ivDel.visibility = View.VISIBLE
//輸入框發生變化就進行網路請求
mainViewModel.getFuzzySearchList(Const.fuzzySearchUrl,etContent.text.toString())
}
}
})
4.2 網路請求部分
介面部分:
-
模糊搜索
@GET請求引數:
key:wdvalue:要搜索的內容地址:
https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su使用以上介面,傳入一個引數wd即可,wd為我們輸入框的內容
interface ApiService { @GET fun getFuzzySearchList(@Url url:String,@Query("wd") content:String): Call<ResponseBody> } -
詳情介面
Url為:
http://www.baidu.com.cn/s?wd=+文本框內容+&cl=3這里我們簡單的通過webview加載該網頁即可
邏輯部分:
- 請求完成后若資料為空,則要隱藏Recyclerview面板,反之則顯示
- 請求完成后對Recyclerview進行更新
5. 具體實作
MainActivity
class MainActivity : AppCompatActivity() {
//創建ViewModel
private val mainViewModel: MainViewModel by lazy {
ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory(application)).get(
MainViewModel::class.java
)
}
private val data = mutableListOf<String>()
private val myAdapter = MyAdapter(data)
override fun onCreate(savedInstanceState: Bundle?) {
...
//Recyclerview相關配置
recy.layoutManager = LinearLayoutManager(this)
recy.adapter = myAdapter
//跳轉到詳情頁
myAdapter.setOnMyClickListener(object :MyAdapter.MyClickListener{
override fun onClick(position: Int) {
val intent = Intent(this@MainActivity,NewsShowActivity::class.java)
val url = Const.serchUrl+data[position]+"&cl=3"
intent.putExtra("url",url)
startActivity(intent)
//跳轉后清空搜索框,隱藏Recyclerview面板
etContent.setText("")
recy.visibility = View.GONE
}
//模糊搜索結果監聽
mainViewModel.getResultLiveData().observe(this, Observer {
if(it.isEmpty()){
//資料為空,隱藏RecyclerView面板
recy.visibility = View.GONE
}else{
recy.visibility = View.VISIBLE
}
//搜索完成后對RecyclerView更新
data.clear()
data.addAll(it)
myAdapter.notifyDataSetChanged()
})
//EditText搜索框進行監聽
etContent.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (etContent.text.isNullOrEmpty()) {
ivDel.visibility = View.GONE
//為空時如果不隱藏, 上一次搜索的結果就會在下面顯示不會隱藏
recy.visibility = View.GONE
} else {
ivDel.visibility = View.VISIBLE
//進行網路請求
mainViewModel.getFuzzySearchList(Const.fuzzySearchUrl,etContent.text.toString())
}
}
})
}
}
MainViewModel
模糊搜索回傳的資料是如下格式,而且是GBK編碼,所以我們在請求成功后需要對資料進行下處理
window.baidu.sug({q:"奧運會",p:false,s:["奧運會","奧運會女子200米蝶泳決賽","奧運會獎牌榜","奧運會賽程","奧運會金牌榜2021","奧運會乒乓球","奧運會直播","奧運會多少年舉辦一次","奧運會在哪看","奧運會裁判"]});
class MainViewModel :ViewModel(){
private val httpClient = OkHttpClient.Builder()
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.writeTimeout(5, TimeUnit.SECONDS)
.build()
private val retrofit: Retrofit =Retrofit.Builder()
.baseUrl("http://a")
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
private val api = retrofit.create(ApiService::class.java)
/**
* 模糊搜索
*/
fun getFuzzySearchList(url:String,content:String){
api.getFuzzySearchList(url,content).enqueue(object : retrofit2.Callback<ResponseBody> {
override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
errorLiveData.value = t.message
}
override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
if(response?.body() != null){
//因為模糊搜索的結果是GBK編碼,所以這里需要處理下
val charset = response.body()!!.contentType()!!.charset()!!
val source = response?.body()?.source()
source?.let {
source.skip(ByteString.decodeHex("efbbbf").size().toLong())
}
val string = response?.body()?.string()
string?.let {
val startIndex = it.indexOf("(")
val endIndex = it.length-2
//截取
val json = it.substring(startIndex+1, endIndex)
val jsonObject = gson.fromJson<ResultBean>(json, ResultBean::class.java)
//對資料進行更新
resultLiveData.value = jsonObject.s
}
}
}
})
}
}
6. 總結
以上就是全部內容,其實也挺簡單的,我們這邊其實就是對EditText監聽,然后對網路請求的結果進行處理就可以了,其余部分的邏輯就是什么時候顯示與隱藏的事情,
如果本文對你有幫助,請別忘記三連,如果有不恰當的地方也請提出來,下篇文章見,
7. 參考文章
百度模糊查詢_三番魚-CSDN博客
呼叫百度搜索介面查詢_greatmind829的專欄-CSDN博客
?android retrofit 請求回傳String資料中文亂碼解決方案
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/291896.html
標籤:其他
