控制器创建重复视图
Controller creating duplicate views
我有一个应用
BaseListActivity
托管
BaseController
-> 充当 ViewPager
ListController
-> ViewPager 的选项卡 1
FavoriteController
-> ViewPager 的选项卡 2
DetailActivity
-> 在选项卡 1 上单击项目时启动
DetailController
-> 在 DetailActivity
中推送到视图
所以代码给你一个想法。
activity.xml:
<LinearLayout android:id="@+id/mainLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.bluelinelabs.conductor.ChangeHandlerFrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
BaseListActivity:
class CoinListActivity : AppCompatActivity() {
private lateinit var router: Router
/**
* Current implementation uses BlueLineLabs Router to navigate between views and handle animations
*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_coin_list)
router = Conductor.attachRouter(this, container, savedInstanceState)
router.setRoot(RouterTransaction.with(CoinBaseController()))
RoomSingleton.initDB(this)
.
.
.
基础控制器:
class CoinBaseController : Controller() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.coin_base_controller, container, false).apply {
viewPager.adapter = TabAdapter()
tabs.setupWithViewPager(viewPager)
}
}
.
.
.
inner class TabAdapter : RouterPagerAdapter(this) {
override fun configureRouter(router: Router, position: Int) {
router.setPopsLastView(true)
when (position) {
0 -> router.pushController(RouterTransaction.with(CoinListController.newInstance()))
1 -> router.pushController(RouterTransaction.with(CoinFavoriteController()))
}
if (router.hasRootController().not())
router.setRoot(RouterTransaction.with(this@CoinBaseController))
}
override fun getCount(): Int = 2
override fun getPageTitle(position: Int): CharSequence? {
return if (position == 0)
"List"
else
"Favorites"
}
}
}
CoinListController:
class CoinListController : BaseMvvmController<CoinListViewModel, CoinListContract.State>(), CoinListAdapter
.CoinListListener {
var list: List<CoinListItem> = emptyList()
var recyclerView: RecyclerView? = null
lateinit var swipeLayout: SwipeRefreshLayout
private val adapter by lazy(LazyThreadSafetyMode.NONE) {
CoinListAdapter(applicationContext!!, this)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View {
val view = inflater.inflate(R.layout.coin_list_controller, container, false)
swipeLayout = view.findViewById(R.id.swipeContainer)
recyclerView = view.findViewById(R.id.listRecycler)
recyclerView!!.layoutManager = LinearLayoutManager(activity)
recyclerView!!.addItemDecoration(DividerItemDecoration(activity,
DividerItemDecoration.VERTICAL))
recyclerView!!.adapter = adapter
recyclerView!!.isNestedScrollingEnabled = false
view.swipeContainer.apply {
this.setOnRefreshListener {
viewModel.getCoinList()
this.isRefreshing = false
}
}
return view
}
override fun onAttach(view: View) {
super.onAttach(view)
with(viewModel) {
if (list.isEmpty()) {
getCoinList()
setSearchListener(view)
} else {
view.listRecycler.adapter = adapter
adapter.notifyDataSetChanged()
}
}
}
override fun onDetach(view: View) {
super.onDetach(view)
view.listRecycler.adapter = null
println("Detached")
}
override fun onCoinClicked(coin: CoinListItem) {
viewModel.onCoinClicked(coin)
}
override fun onFavoriteClicked(coinFavoriteItem: CoinFavoriteItem) {
viewModel.onFavoriteClicked()
}
override val viewModel: CoinListViewModel = get().koin.get()
override fun onStateChange(state: Mvvm.State) {
when (state) {
is CoinListContract.State.CoinListReceived -> {
list = state.coins
adapter.addItems(list)
}
is CoinListContract.State.CoinItemClicked -> {
Snackbar.make(view!!, "Coin Item Clicked", Snackbar.LENGTH_SHORT)
//router.onActivityStarted()
startActivity(CoinDetailActivity.getLaunchIntent(activity!!, state.coin))
}
is CoinListContract.State.FavoriteClicked -> {
Snackbar.make(view!!, "Favorite Button Clicked", Snackbar.LENGTH_SHORT)
}
is CoinListContract.State.QueryRan -> {
adapter.addItems(state.searchList)
}
is CoinListContract.State.Error -> {
Log.d("OnStateChange", state.throwable.localizedMessage!!)
}
}
}
所以问题出在CoinListController
,当我点击一个列表项时,DetailActivity
被启动,然后我退出..return到CoinListController
。
但是,对于项目的每次后续点击,都会添加一个额外的侦听器(我认为)。因此,如果我第 3 次单击某个项目,CoinListController.onCoinClicked
将被调用 3 次,从而创建 CoinDetailActivity
的 3 个实例。所以我必须按回键 3 次才能 return 到 CoinListController
.
此行为在调试模式下不存在..
我在分离时将适配器设置为空。什么在控制器的生命周期中持续存在?是我在适配器中设置的侦听器还是其他?
在 CoinListActivity
和 CoinBaseController
中设置根两次导致了问题
我有一个应用
BaseListActivity
托管
BaseController
-> 充当 ViewPager
ListController
-> ViewPager 的选项卡 1
FavoriteController
-> ViewPager 的选项卡 2
DetailActivity
-> 在选项卡 1 上单击项目时启动
DetailController
-> 在 DetailActivity
所以代码给你一个想法。
activity.xml:
<LinearLayout android:id="@+id/mainLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.bluelinelabs.conductor.ChangeHandlerFrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
BaseListActivity:
class CoinListActivity : AppCompatActivity() {
private lateinit var router: Router
/**
* Current implementation uses BlueLineLabs Router to navigate between views and handle animations
*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_coin_list)
router = Conductor.attachRouter(this, container, savedInstanceState)
router.setRoot(RouterTransaction.with(CoinBaseController()))
RoomSingleton.initDB(this)
.
.
.
基础控制器:
class CoinBaseController : Controller() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.coin_base_controller, container, false).apply {
viewPager.adapter = TabAdapter()
tabs.setupWithViewPager(viewPager)
}
}
.
.
.
inner class TabAdapter : RouterPagerAdapter(this) {
override fun configureRouter(router: Router, position: Int) {
router.setPopsLastView(true)
when (position) {
0 -> router.pushController(RouterTransaction.with(CoinListController.newInstance()))
1 -> router.pushController(RouterTransaction.with(CoinFavoriteController()))
}
if (router.hasRootController().not())
router.setRoot(RouterTransaction.with(this@CoinBaseController))
}
override fun getCount(): Int = 2
override fun getPageTitle(position: Int): CharSequence? {
return if (position == 0)
"List"
else
"Favorites"
}
}
}
CoinListController:
class CoinListController : BaseMvvmController<CoinListViewModel, CoinListContract.State>(), CoinListAdapter
.CoinListListener {
var list: List<CoinListItem> = emptyList()
var recyclerView: RecyclerView? = null
lateinit var swipeLayout: SwipeRefreshLayout
private val adapter by lazy(LazyThreadSafetyMode.NONE) {
CoinListAdapter(applicationContext!!, this)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View {
val view = inflater.inflate(R.layout.coin_list_controller, container, false)
swipeLayout = view.findViewById(R.id.swipeContainer)
recyclerView = view.findViewById(R.id.listRecycler)
recyclerView!!.layoutManager = LinearLayoutManager(activity)
recyclerView!!.addItemDecoration(DividerItemDecoration(activity,
DividerItemDecoration.VERTICAL))
recyclerView!!.adapter = adapter
recyclerView!!.isNestedScrollingEnabled = false
view.swipeContainer.apply {
this.setOnRefreshListener {
viewModel.getCoinList()
this.isRefreshing = false
}
}
return view
}
override fun onAttach(view: View) {
super.onAttach(view)
with(viewModel) {
if (list.isEmpty()) {
getCoinList()
setSearchListener(view)
} else {
view.listRecycler.adapter = adapter
adapter.notifyDataSetChanged()
}
}
}
override fun onDetach(view: View) {
super.onDetach(view)
view.listRecycler.adapter = null
println("Detached")
}
override fun onCoinClicked(coin: CoinListItem) {
viewModel.onCoinClicked(coin)
}
override fun onFavoriteClicked(coinFavoriteItem: CoinFavoriteItem) {
viewModel.onFavoriteClicked()
}
override val viewModel: CoinListViewModel = get().koin.get()
override fun onStateChange(state: Mvvm.State) {
when (state) {
is CoinListContract.State.CoinListReceived -> {
list = state.coins
adapter.addItems(list)
}
is CoinListContract.State.CoinItemClicked -> {
Snackbar.make(view!!, "Coin Item Clicked", Snackbar.LENGTH_SHORT)
//router.onActivityStarted()
startActivity(CoinDetailActivity.getLaunchIntent(activity!!, state.coin))
}
is CoinListContract.State.FavoriteClicked -> {
Snackbar.make(view!!, "Favorite Button Clicked", Snackbar.LENGTH_SHORT)
}
is CoinListContract.State.QueryRan -> {
adapter.addItems(state.searchList)
}
is CoinListContract.State.Error -> {
Log.d("OnStateChange", state.throwable.localizedMessage!!)
}
}
}
所以问题出在CoinListController
,当我点击一个列表项时,DetailActivity
被启动,然后我退出..return到CoinListController
。
但是,对于项目的每次后续点击,都会添加一个额外的侦听器(我认为)。因此,如果我第 3 次单击某个项目,CoinListController.onCoinClicked
将被调用 3 次,从而创建 CoinDetailActivity
的 3 个实例。所以我必须按回键 3 次才能 return 到 CoinListController
.
此行为在调试模式下不存在..
我在分离时将适配器设置为空。什么在控制器的生命周期中持续存在?是我在适配器中设置的侦听器还是其他?
在 CoinListActivity
和 CoinBaseController
中设置根两次导致了问题