Я пытаюсь создать поисковое представление внутри фрагмента, который при поиске запрашивает данные из API бэкэнда. Результаты разбиты на страницы, поэтому я использую PageKeyedDataSource для отображения результатов в представлении рециркулятора.Поэтому, когда я выполняю поисковый запрос, в результате ничего не отображается, даже ошибки или предупреждения
Если с моим кодом что-то не так, помогите мне !! 1 Я застрял здесь на несколько недель !!!
Код пользовательского интерфейса:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.users_fragment, container, false)
val context = getContext() ?: return view
val adapter = UserAdapter(context)
rec_view = view.findViewById<RecyclerView>(R.id.usersRecycler)
rec_view.layoutManager = LinearLayoutManager(MyApplication.getContext())
viewModel = viewModel()
initAdapter()
return view
}
private fun initAdapter() {
adapter = UserAdapter(context)
rec_view.adapter = adapter
viewModel.items.observe(this,object:Observer<PagedList<Result>>{
override fun onChanged(t: PagedList<Result>?) {
adapter.submitList(t)
adapter.notifyDataSetChanged()
}
})
}
private fun viewModel():UsersViewModel {
val viewModelFactory = InjectorUtils.provideUserViewModel(context!!)
return ViewModelProviders.of(this,viewModelFactory)[UsersViewModel::class.java]
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
inflater?.inflate(R.menu.options_menu,menu)
var searchItem:MenuItem = menu!!.findItem(R.id.search)
var searchManager = activity?.getSystemService(Context.SEARCH_SERVICE) as SearchManager
searchView = SearchView((context as FeedActivity).supportActionBar?.themedContext ?: context)
searchItem.apply {
setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW or MenuItem.SHOW_AS_ACTION_IF_ROOM)
actionView = searchView
}
if(searchView != null){
searchView!!.setOnQueryTextListener(object:SearchView.OnQueryTextListener{
override fun onQueryTextSubmit(query: String): Boolean {
viewModel.items.observe(this@UsersFragment,object :Observer<PagedList<Result>>{
override fun onChanged(t: PagedList<Result>?) {
adapter.submitList(t)
adapter.notifyDataSetChanged()
Timber.d("ViewModel Observed inside OnQueryTextSubmit()")
}
})
Timber.d(query)
return true
}
override fun onQueryTextChange(newText: String): Boolean {
/*
* Do Nothing
* */
return true
}
})
}
Адаптер:
public class UserAdapter extends PagedListAdapter<Result,UserAdapter.UserViewHolder>{
private Context ctx;
public UserAdapter(Context ctx) {
super(diffCallback);
this.ctx = ctx;
}
private static DiffUtil.ItemCallback<Result> diffCallback =
new DiffUtil.ItemCallback<Result>() {
@Override
public boolean areItemsTheSame(Result oldItem, Result newItem) {
return oldItem.getPk() == newItem.getPk();
}
@Override
public boolean areContentsTheSame(Result oldItem, Result newItem) {
return oldItem.equals(newItem);
}
};
@NonNull
@Override
public UserViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
Timber.d("onCreateViewHolder() --> Adapter");
View view = LayoutInflater.from(ctx).inflate(R.layout.user_row,parent,false);
return new UserViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull UserViewHolder holder, int position) {
Timber.d("onBindViewHolder() --> Adapter");
Result result = super.getItem(position);
if(result != null){
/**
* Set Data to Views
* using @{holder}
* */
holder.textView.setText(result.getUsername());
Glide
.with(ctx)
.load(result.getProfilePic())
.into(holder.imageView);
}
else {
Toast.makeText(ctx,"result is null",Toast.LENGTH_LONG).show();
}
}
public class UserViewHolder extends RecyclerView.ViewHolder {
TextView textView ;
ImageView imageView;
public UserViewHolder(View itemView) {
super(itemView);
Timber.d("UserViewHOlder");
textView = itemView.findViewById(R.id.username);
imageView = itemView.findViewById(R.id.userImage);
}
}
}
ViewModel:
class UsersViewModel internal constructor(private val repository: UserRepository): ViewModel() {
private val searchQuery = MutableLiveData<String>()
private val userResult = map(searchQuery) {
repository.showUsers(it)
}
val items = switchMap(userResult) { it.value as LiveData<PagedList<Result>> }
fun showSearchResults(searchQuery: String): Boolean {
if (this.searchQuery.value == searchQuery) {
return false
}
this.searchQuery.value = searchQuery
return true
}
fun showResult(searchQuery: String): LiveData<PagedList<Result>> {
return repository.showUsers(searchQuery)
}
}
Источник данных:
class UserDataSource(private var param:String):PageKeyedDataSource<Int,Result>(){
companion object {
private val apiClient = ApiClient.getApiClient().create(UserClient::class.java)
var page = 1
}
private var query:String
var executor = Executors.newSingleThreadExecutor()
init {
query = param
}
override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, Result>) {
Timber.d(query+"loadInitial()")
val call: Call<UserSearchResult> = apiClient.getUserData(page, query)
call.enqueue(object : Callback<UserSearchResult> {
override fun onFailure(call: Call<UserSearchResult>?, t: Throwable?) {
Timber.d("loadInitial() failure")
}
override fun onResponse(call: Call<UserSearchResult>?, response: Response<UserSearchResult>?) {
var user_result = response?.body()
Log.d("loadInitial() --> ",response?.body().toString())
if (user_result == null) {
onFailure(call, HttpException(response))
return
}
callback.onResult(
user_result.results,
0,
user_result.count,
null,
page + 1
)
}
})
}
override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, Result>) {
page = params.key
val call:Call<UserSearchResult> = apiClient.getUserData(page,query)
call.enqueue(object :Callback<UserSearchResult>{
override fun onFailure(call: Call<UserSearchResult>?, t: Throwable?) {
Timber.d("loadAfter() Failure")
}
override fun onResponse(call: Call<UserSearchResult>?, response: Response<UserSearchResult>?) {
var user_result = response?.body()
Log.d("loadAfter() --> ",response?.body().toString())
if(user_result == null){
onFailure(call,HttpException(response))
return
}
callback.onResult(
user_result.results,
page+1
)
}
})
}
override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, Result>) {
/*
* We only append data after retrieving
* */
}
}
DataSourceFactory:
public class UserDataSourceFactory(param:String) : DataSource.Factory<Int, Result>() {
private var query:String
val sourceLiveData = MutableLiveData<UserDataSource>()
init {
query = param
}
override fun create(): DataSource<Int, Result> {
Timber.d("UserDataSourcefactory create()")
val source:UserDataSource = UserDataSource(query)
sourceLiveData.postValue(source)
return source
}
}