PopBackStack вызывает OnCreateView каждый раз
У меня есть два фрагмента. Первый - фрагмент с recyclerview и поисковым текстовым полем:
Как видите, при запуске приложения, открывается этот фрагмент и загружаются дефолтные картинки. Если что-то ввести в поисковой строке, то будет произведён поиск и в recyclerview загрузятся картинки, соответствующие словам в поиске:
class FragmentMain : Fragment() {
private lateinit var mService: RetrofitServices
private lateinit var linearLayoutManager: LinearLayoutManager
private lateinit var gridLayoutManager: GridLayoutManager
private lateinit var adapterOne: OneAdapter
private lateinit var adapterTwo: TwoAdapter
lateinit var dialog: AlertDialog
lateinit var switchCompat: SwitchCompat
private lateinit var recyclerView: RecyclerView
lateinit var editText: EditText
lateinit var labels: Labels
lateinit var toolbar: Toolbar
var fragment: FragmentMain = this
lateinit var stateHelper: FragmentStateHelper
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val view: View = inflater.inflate(R.layout.fragment_main, container, false)
switchCompat = view.findViewById(R.id.customSwitch)
recyclerView = view.findViewById(R.id.recyclerPictures)
toolbar = view.findViewById(R.id.toolbar)
editText = view.findViewById(R.id.edit_search)
mService = Common.retrofitService
labels = Labels()
stateHelper = FragmentStateHelper(requireActivity().supportFragmentManager)
dialog = SpotsDialog.Builder().setCancelable(true).setContext(context).build()
linearLayoutManager = LinearLayoutManager(context)
gridLayoutManager = GridLayoutManager(context, 2)
if (savedInstanceState != null){
getAllPicturesList(savedInstanceState.getString("key")!!)
} else {
getAllPicturesList(editText.text.toString())
}
Log.d("TAG", "Search is: " + editText.text.toString())
switchCompat.setOnCheckedChangeListener { buttonView, isChecked ->
if (switchCompat.isChecked) {
setOneAdapter(labels)
} else {
setTwoAdapter(labels)
}
}
if (savedInstanceState == null){
getAllPicturesList(editText.text.toString())
} else {
stateHelper.restoreState(this, "key")
}
editText.setOnKeyListener(object : View.OnKeyListener{
override fun onKey(v: View?, keyCode: Int, event: KeyEvent?): Boolean {
if (keyCode == EditorInfo.IME_ACTION_SEARCH ||
keyCode == EditorInfo.IME_ACTION_DONE ||
event?.action == KeyEvent.ACTION_DOWN &&
event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
getAllPicturesList(editText.text.toString())
return true
} else{
return false
}
}
})
return view
}
private fun setOneAdapter(labels: Labels) {
adapterOne = OneAdapter(context, labels)
recyclerView.layoutManager = linearLayoutManager
recyclerView.adapter = adapterOne
adapterOne.notifyDataSetChanged()
}
private fun setTwoAdapter(labels: Labels) {
adapterTwo = TwoAdapter(context, labels)
recyclerView.layoutManager = gridLayoutManager
recyclerView.adapter = adapterTwo
adapterTwo.notifyDataSetChanged()
}
private fun getAllPicturesList(search: String) {
dialog.show()
mService.getPicturesList(search).enqueue(object : Callback<Labels> {
override fun onResponse(call: Call<Labels>, response: Response<Labels>) {
labels = response.body() as Labels
if (switchCompat.isChecked) {
setOneAdapter(labels)
} else {
setTwoAdapter(labels)
}
dialog.dismiss()
}
override fun onFailure(call: Call<Labels>, t: Throwable) {
}
})
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("key", editText.text.toString())
}
}
По нажатию на картинку, открывается фрагмент с детальным описанием картинки:
class FragmentDetails : Fragment() {
private lateinit var imageView: ImageView
private lateinit var imageUser: ImageView
private lateinit var textUser: TextView
private lateinit var textTags: TextView
private lateinit var textLikes: TextView
private lateinit var textComments: TextView
private lateinit var textViews: TextView
private lateinit var imageSave: ImageView
private lateinit var imageBack: ImageView
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val view: View = inflater.inflate(R.layout.fragment_details, container, false)
val hits: Hits?
imageView = view.findViewById(R.id.image_details)
imageUser = view.findViewById(R.id.image_user_details)
textUser = view.findViewById(R.id.text_user_details)
textTags = view.findViewById(R.id.text_tags_details)
textLikes = view.findViewById(R.id.text_likes_details)
textComments = view.findViewById(R.id.text_comments_details)
textViews = view.findViewById(R.id.text_views_details)
imageSave = view.findViewById(R.id.image_save)
imageBack = view.findViewById(R.id.image_back)
textLikes.setCompoundDrawablesWithIntrinsicBounds(
R.drawable.ic_baseline_favorite_24,
0,
0,
0
)
textComments.setCompoundDrawablesWithIntrinsicBounds(
R.drawable.ic_baseline_comment_24,
0,
0,
0
)
textViews.setCompoundDrawablesWithIntrinsicBounds(
R.drawable.ic_baseline_remove_red_eye_24,
0,
0,
0
)
val bundle: Bundle? = arguments
if (bundle != null) {
hits = bundle.getParcelable("item_key")
Picasso.get().load(hits?.largeImageURL).into(imageView)
if (hits?.userImageURL != "") {
Picasso.get().load(hits?.userImageURL).into(imageUser)
}
textUser.text = hits?.user
textTags.text = hits?.tags
textLikes.text = hits?.likes
textViews.text = hits?.views
textComments.text = hits?.comments
imageSave.setOnClickListener {
download(hits!!)
Snackbar.make(imageSave, "Downloading...", Snackbar.LENGTH_LONG).show()
}
} else {
Log.d("TAG", "Fail")
}
imageBack.setOnClickListener {
parentFragmentManager.popBackStack()
}
return view
}
private fun download(hits: Hits) {
val filename = hits.id + ".jpg"
val dirname = "pixabay"
val downloadUrlOfImage = hits.largeImageURL
val direct = File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
.absolutePath + "/" + dirname + "/"
)
if (!direct.exists()) {
direct.mkdir()
Log.d("TAG", "dir created for first time")
}
val dm = context?.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val downloadUri: Uri = Uri.parse(downloadUrlOfImage)
val request = DownloadManager.Request(downloadUri)
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
.setTitle(filename)
.setMimeType("image/jpeg")
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
.setDestinationInExternalPublicDir(
Environment.DIRECTORY_PICTURES,
File.separator + dirname + File.separator.toString() + filename
)
dm.enqueue(request)
}
}
Проблема для меня заключается в том, что по возвращению в прошлый фрагмент, вызывается метод onCreateView и в recyclerview загружаются дефолтные картинки, хотя в текстовом поле значение поиска сохраняется. И когда я получаю значение текстового поля, он выдаёт null, хотя в нём содержится текст, и его видно. Получается, что пользователю нужно снова запустить процесс поиска, чтобы вернуться к картинкам, которые он искал ранее:
Я пробовал производить поиск снова по запуску метода onResume. Но выходит, что стоит просто свернуть приложение, как по возвращению он обновит список (Плохо, если пользователь успел пролистать список вниз), savedInstanceState тоже не помогает. Как можно этого избежать?
Класс FragmentStateHelper, который я взял из ответа на другой похожий вопрос. К сожалению, он не помог. Его использование ни на что не влияет. Что с ним, что без него. Вставил бы ссылку на тот ответ, но потерял её(
class FragmentStateHelper(val fragmentManager: FragmentManager) {
private val fragmentSavedStates = mutableMapOf<String, Fragment.SavedState?>()
fun restoreState(fragment: Fragment, key: String) {
fragmentSavedStates[key]?.let { savedState ->
// We can't set the initial saved state if the Fragment is already added
// to a FragmentManager, since it would then already be created.
if (!fragment.isAdded) {
fragment.setInitialSavedState(savedState)
}
}
}
fun saveState(fragment: Fragment, key: String) {
// We can't save the state of a Fragment that isn't added to a FragmentManager.
if (fragment.isAdded ?: false) {
fragmentSavedStates[key] = fragmentManager.saveFragmentInstanceState(fragment)
}
}
}



