繁体   English   中英

如何防止活动在更改其方向后重新启动

[英]How to prevent activity to restart after changing its orientation

我是使用 KOTLIN 开发 android 的新手,我的活动包含如下图所示的片段(图 1),问题是每当我尝试将方向从纵向更改为横向时,活动都会返回到以前的活动(例如重新启动它)。

我尝试将android:configChanges="orientation|screenSize|keyboardHidden"添加到我的AndroidManifest.xml中,效果很好,但有人说不建议使用它。

你们能告诉我或向我展示解决此问题的最佳实践吗?

图片 1

图 1

代码

MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        title = resources.getString(R.string.title_visit)
        loadFragment(VisitFragment())
        navigation_menu.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
    }

    private val mOnNavigationItemSelectedListener =
        BottomNavigationView.OnNavigationItemSelectedListener { item ->
            when (item.itemId) {
                R.id.menu_visit -> {
                    loadFragment(VisitFragment())
                    title = resources.getString(R.string.title_visit)
                    return@OnNavigationItemSelectedListener true
                }

                R.id.menu_customer -> {
                    loadFragment(CustomerFragment())
                    title = resources.getString(R.string.title_customer)
                    return@OnNavigationItemSelectedListener true
                }

                R.id.menu_new_merchant -> {
                    loadFragment(NewMerchantFragment())
                    title = resources.getString(R.string.title_new_merchant)
                    return@OnNavigationItemSelectedListener true
                }

                R.id.menu_history -> {
                    loadFragment(HistoryFragment())
                    title = resources.getString(R.string.title_history)
                    return@OnNavigationItemSelectedListener true
                }

                R.id.menu_profile -> {
                    loadFragment(ProfileFragment())
                    title = resources.getString(R.string.title_profile)
                    return@OnNavigationItemSelectedListener true
                }
            }
            false
    }

    private fun loadFragment(fragment: Fragment) {
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.container, fragment)
        transaction.addToBackStack(null)
        transaction.commit()
    }
}

访问Fragment.kt

class VisitFragment : Fragment() {
    private lateinit var viewPager: ViewPager
    private lateinit var tabs: TabLayout

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_visit, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val fragmentAdapter = PagerAdapter(childFragmentManager)
        pager.adapter = fragmentAdapter
        tabs_main.setupWithViewPager(pager)
    }

    fun setNumber() {
        val tabs = tabs_main.getTabAt(0)
        val badge = tabs?.orCreateBadge
        // Customize badge
        badge?.number = 1
    }
}

最新访问片段.kt

class LatestVisitFragment : Fragment() {
    lateinit var latestVisitAdapter: LatestVisitAdapter
    lateinit var recyclerView: RecyclerView
    private val testinstance: ArrayList<TestResponseItem> = ArrayList()
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_latest_visit, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        loadDataLatestVisit()
    }

    private fun loadDataLatestVisit(){
        ApiConfig().getService()
            .getUsers()
            .enqueue(object : Callback<List<TestResponseItem>> {
                override fun onFailure(call: Call<List<TestResponseItem>>, t: Throwable) {
                    Toast.makeText(context, t.localizedMessage, Toast.LENGTH_SHORT).show()
                }

                override fun onResponse(
                    call: Call<List<TestResponseItem>>,
                    response: Response<List<TestResponseItem>>
                ) {
                    rv_latest_visit.adapter = LatestVisitAdapter(response.body())
                }

            })
    }
}

最新访问适配器.kt

class LatestVisitAdapter(val data: List<TestResponseItem>?) :
    RecyclerView.Adapter<LatestVisitAdapter.MyHolder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
        val v =
            LayoutInflater.from(parent.context).inflate(R.layout.item_latest_visit, parent, false)
        return MyHolder(v)
    }

    override fun getItemCount(): Int = data?.size ?: 0

    override fun onBindViewHolder(holder: LatestVisitAdapter.MyHolder, position: Int) {
        holder.bind(data?.get(position))
    }

    class MyHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(get: TestResponseItem?) {
            itemView.txt_merchant_name.text = get?.name
            itemView.txt_owner_name.text = get?.email
            val address =
                "${get?.address?.street},${get?.address?.city}, ${get?.address?.suite}, ${get?.address?.zipcode}"
            itemView.txt_address.text = address
        }
    }

}

确实不建议在配置更改时阻止活动重启

推荐的方法是保存和恢复 UI state使用 ViewModel 其中任何一个都可以解决您的问题,但最好使用 ViewModel 方法。


保存和恢复 UI state

保存 state

在活动开始之前,但在配置更改发出信号之后,如果您要保存活动 state,则覆盖Activity.onSaveInstanceState(Bundle) ,如果要保存片段 state,则覆盖 `Fragment.onSaveInstanceState(Bundle)。

override fun onSaveInstanceState(outState: Bundle?) {
  // Save your data into outState data bundle. And then make sure to
  // call the super method.
  super.onSaveInstanceState(outState)
}

恢复 state

由于配置更改而重新启动活动后,恢复以前保存的数据并将其应用到 UI。

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  // ... inflate layout, etc...
  if (savedInstanceState != null) {
    // If savedInstanceState is not null, that means this activity is restoring from
    // config changes. All your saved data in onSaveInstanceState() should be accessible
    // from savedInstanceState bundle.
    // ... restore values from savedInstanceState and apply to your views ...
  } else {
    // Initialize vie
  }
}

使用视图模型

这种方法是 Google 作为 Android Jetpack 库的一部分引入的相对较新的方法。 您的数据不会覆盖onSaveInstanceState(Bundle) and checking null for null, your data is persisted inside a ViewModel` 中,并且不会因配置更改而保留。

基本的

ViewModel中初始化您的数据并从您的活动或片段中访问它们。

class MyViewModel : ViewModel() {
  var myList: List<User> = emptyList()
  var currentTabIndex: Int = 0

  init {
    // Initialize your data here...
  }
}
class MyFragment : Fragment() {
  private val model by viewModels<MyViewModel>()

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // ... inflate layout, etc...
    viewPager.setCurrentItem(model.currentTabIndex, false)
    // Fetch the values from `ViewModel` and apply to your fragment.
  }
}

更多关于ViewModel

为了更好地使用ViewModel ,最好从官方综合指南中学习。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM