我使用ViewPager2与FragmentStatePagerAdapter,并设置OffscreenPageLimit=1。每个片段都包含一个表面(通过TextureView获得),要在上面绘制。
代码相当简单。
package com.example.testapplication
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.graphics.SurfaceTexture
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.*
import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import kotlinx.android.synthetic.main.item_fragment.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val pageAdapter = object: FragmentStateAdapter(this) {
override fun createFragment(position: Int): Fragment {
return ItemFragment.create(position)
}
override fun getItemCount(): Int = 100
}
val viewpager = findViewById<ViewPager2>(R.id.viewpager).apply {
offscreenPageLimit = 1
adapter = pageAdapter
}
viewpager.currentItem = 0
}
class ItemFragment: Fragment() {
private var position: Int = 0
companion object {
private val ARG = ItemFragment::class.java.name+"_arg"
fun create(position: Int): ItemFragment {
return ItemFragment().also {
it.arguments = Bundle().apply {
putInt(ARG, position)
}
}
}
}
private val TAG: String
get() = "Fragment_${position}"
override fun onAttach(context: Context) {
super.onAttach(context)
position = arguments!!.getInt(ARG, 0)
Log.d(TAG, "onAttach")
}
override fun onDetach() {
super.onDetach()
Log.d(TAG, "onDetach")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "onCreate")
}
override fun onStart() {
super.onStart()
Log.d(TAG, "onStart")
}
override fun onResume() {
super.onResume()
Log.d(TAG, "onResume")
}
override fun onPause() {
super.onPause()
Log.d(TAG, "onPause")
}
override fun onStop() {
super.onStop()
Log.d(TAG, "onStop")
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy")
}
@SuppressLint("InflateParams")
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
Log.d(TAG, "onCreateView")
return inflater.inflate(R.layout.item_fragment, null)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
textview.text = position.toString()
textureview.surfaceTextureListener = object: TextureView.SurfaceTextureListener {
override fun onSurfaceTextureSizeChanged(
surface: SurfaceTexture?,
width: Int,
height: Int
) {
}
override fun onSurfaceTextureUpdated(surface: SurfaceTexture?) {
}
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture?): Boolean {
Log.d(TAG, "onSurfaceTextureDestroyed")
return true
}
override fun onSurfaceTextureAvailable(
surfaceTexture: SurfaceTexture?,
width: Int,
height: Int
) {
Log.d(TAG, "onSurfaceTextureAvailable")
val surface = Surface(surfaceTexture)
val canvas = surface.lockCanvas(null)
canvas.drawColor(Color.CYAN)
surface.unlockCanvasAndPost(canvas)
surface.release()
}
}
}
override fun onDestroyView() {
super.onDestroyView()
Log.d(TAG, "onDestroyView")
}
}
}
布局如下:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
item_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextureView
android:id="@+id/textureview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>
屏幕外的碎片是按照预期创建的。然而,销毁行为并不是我所期望的。你可以看到fragment0没有被销毁,直到我滚动到fragment4。但是当我滚动到fragment2时,fragment0上的surface被销毁了。
04-21 17:51:20.527 20921 20921 D Fragment_0: onAttach
04-21 17:51:20.527 20921 20921 D Fragment_0: onCreate
04-21 17:51:20.527 20921 20921 D Fragment_0: onCreateView
04-21 17:51:20.531 20921 20921 D Fragment_0: onStart
04-21 17:51:20.531 20921 20921 D Fragment_0: onResume
04-21 17:51:20.533 20921 20921 D Fragment_1: onAttach
04-21 17:51:20.533 20921 20921 D Fragment_1: onCreate
04-21 17:51:20.534 20921 20921 D Fragment_1: onCreateView
04-21 17:51:20.536 20921 20921 D Fragment_1: onStart
04-21 17:51:20.540 20921 20921 D Fragment_0: onSurfaceTextureAvailable
04-21 17:51:20.544 20921 20921 D Fragment_1: onSurfaceTextureAvailable
04-21 17:51:22.082 20921 20921 D Fragment_2: onAttach
04-21 17:51:22.083 20921 20921 D Fragment_2: onCreate
04-21 17:51:22.083 20921 20921 D Fragment_2: onCreateView
04-21 17:51:22.087 20921 20921 D Fragment_2: onStart
04-21 17:51:22.428 20921 20921 D Fragment_0: onPause
04-21 17:51:22.428 20921 20921 D Fragment_1: onResume
04-21 17:51:22.430 20921 20921 D Fragment_2: onSurfaceTextureAvailable
04-21 17:51:23.342 20921 20921 D Fragment_3: onAttach
04-21 17:51:23.342 20921 20921 D Fragment_3: onCreate
04-21 17:51:23.342 20921 20921 D Fragment_3: onCreateView
04-21 17:51:23.348 20921 20921 D Fragment_3: onStart
04-21 17:51:23.690 20921 20921 D Fragment_0: onSurfaceTextureDestroyed
04-21 17:51:23.691 20921 20921 D Fragment_1: onPause
04-21 17:51:23.691 20921 20921 D Fragment_2: onResume
04-21 17:51:23.693 20921 20921 D Fragment_3: onSurfaceTextureAvailable
04-21 17:51:24.452 20921 20921 D Fragment_4: onAttach
04-21 17:51:24.453 20921 20921 D Fragment_4: onCreate
04-21 17:51:24.453 20921 20921 D Fragment_4: onCreateView
04-21 17:51:24.456 20921 20921 D Fragment_4: onStart
04-21 17:51:24.796 20921 20921 D Fragment_1: onSurfaceTextureDestroyed
04-21 17:51:24.798 20921 20921 D Fragment_2: onPause
04-21 17:51:24.798 20921 20921 D Fragment_3: onResume
04-21 17:51:24.799 20921 20921 D Fragment_4: onSurfaceTextureAvailable
04-21 17:51:28.500 20921 20921 D Fragment_5: onAttach
04-21 17:51:28.500 20921 20921 D Fragment_5: onCreate
04-21 17:51:28.501 20921 20921 D Fragment_5: onCreateView
04-21 17:51:28.506 20921 20921 D Fragment_5: onStart
04-21 17:51:28.853 20921 20921 D Fragment_2: onSurfaceTextureDestroyed
04-21 17:51:28.855 20921 20921 D Fragment_0: onStop
04-21 17:51:28.855 20921 20921 D Fragment_0: onDestroyView
04-21 17:51:28.856 20921 20921 D Fragment_0: onDestroy
04-21 17:51:28.856 20921 20921 D Fragment_0: onDetach
04-21 17:51:28.857 20921 20921 D Fragment_3: onPause
04-21 17:51:28.857 20921 20921 D Fragment_4: onResume
04-21 17:51:28.858 20921 20921 D Fragment_5: onSurfaceTextureAvailable
这是非常恼人的,因为碎片和它的表面不是同时被破坏的。有谁知道这是怎么回事吗?