有一个相当简单的场景给我带来了很多麻烦.我正在使用嵌入式片段制作一个非常简单的Activity.这个片段只是一个显示一些图像的Gridview.当引用使用Kotlin扩展的Gridview直接引用XML id时会出现问题.这是什么问题?kotlinx不能用于静态片段吗?
错误:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.android_me/com.example.android.android_me.ui.MainActivity}: java.lang.IllegalStateException: gridview_all_parts must not be null
Caused by: java.lang.IllegalStateException: gridview_all_parts must not be null at com.example.android.android_me.ui.MasterListFragment.onActivityCreated(MasterListFragment.kt:22)
Run Code Online (Sandbox Code Playgroud)
带有令人反感的代码行的片段
import kotlinx.android.synthetic.main.fragment_master_list.*
class MasterListFragment: Fragment() {
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val layoutView = inflater?.inflate(R.layout.fragment_master_list, container, false)
return layoutView
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
//If this is removed, code runs
gridview_all_parts.adapter = MasterListAdapter(activity, AndroidImageAssets.getAll())
super.onActivityCreated(savedInstanceState)
}
}
Run Code Online (Sandbox Code Playgroud)
片段布局:
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gridview_all_parts"
android:layout_width="match_parent" android:layout_height="match_parent"/>
Run Code Online (Sandbox Code Playgroud)
父活动布局 …
我已经使用Android体系结构中的ViewModel已有一段时间了,并且恪守从不将ViewModel暴露于上下文/视图(Android Framework / UI)。但是,最近我遇到了一个有趣的问题。
制作计时器应用程序时,启动计时器时,将在运行计时器的后台运行服务。这样,当应用程序关闭时,计时器仍在通知栏中的前台运行,直到所有计时器都停止。但是,这意味着我所有的Timer对象和状态都包含在此服务中。我的UI需要在每个刻度上更新,但模型不一定需要更新。ViewModel如何适应这种情况?
活动是否应该每次都接收LocalBroadcasts并通知ViewModel?是否应该从Service-> Activity-> VM中读取UI状态?看起来服务似乎是ViewModel,但这似乎并不高效。
android mvvm android-service android-architecture-components
在Android中学习ViewModels时,出现了一个问题,感觉像是要解决Kotlin。在下面的代码中,我们可以看到MutableLiveData值正在用于编辑值和指标。但是,我们不希望这些可变值暴露给其他任何事物,特别是Android生命周期的成员。我们确实希望Android Lifecycle成员有权读取值,但不能设置它们。因此,下面显示的3个公开函数是LiveData <>不可变类型。
有没有更简单或更简洁的方法来公开可以在内部编辑的只读值?这似乎是Kotlin要避免的事情:样板冗长。
class HomeListViewModel: ViewModel(){
//Private mutable data
private val repositories = MutableLiveData<List<Repo>>()
private val repoLoadError = MutableLiveData<Boolean>()
private val loading = MutableLiveData<Boolean>()
//Exposed uneditable LIveData
fun getRepositories():LiveData<List<Repo>> = repositories
fun getLoadError(): LiveData<Boolean> = repoLoadError
fun getLoadingStatuses(): LiveData<Boolean> = loading
init{...//Do some stuff to MutableLiveData<>
}
}
Run Code Online (Sandbox Code Playgroud)
可能类似的非Android场景是:
class ImmutableAccessExample{
private val theThingToBeEditedInternally = mutableListOf<String>()
fun theThingToBeAccessedPublicly(): List<String> = theThingToBeEditedInternally
init {
theThingToBeEditedInternally.add(0, "something")
}
}
Run Code Online (Sandbox Code Playgroud) 在使用Android学习Kotlin的过程中,编译失败以及通常无用的错误文本让我感到难过.错误文本说明如下:
使用提供的参数不能调用以下任何函数.在android.app.FragmentTransaction中定义的android.app.FragmentTransaction add(Int,Fragment!)中定义的add(Fragment!,String!)
在这两个例子中碎片!文字以红色突出显示.我知道Kotlin引用了带有!的Java类,但我似乎无法理解为什么它对我提供输入的方式不满意.
任何见解将不胜感激.
fun displayEditRoutine(){
//Set our variables
var ft = fragmentManager.beginTransaction()
//Basic "newInstance" constructor to avoid omitting necessary variables
var frag = EditRoutine.newInstance(mRoutineID,this)
//Here is where error occurs
ft.add(R.id.are_container, frag).commit()
}
Run Code Online (Sandbox Code Playgroud)
正在引用的EditRoutine类:
class EditRoutine : Fragment() {
//Variables
private var mRoutineID: String? = null
private var mListener: OnEditRoutineFragmentListener? = null
//Views
@BindView(R.id.fer_routineName) internal var vRoutine: TextInputEditText? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (arguments != null) {
mRoutineID = arguments.getString(Keys.b_RoutineID)
}
}
override …Run Code Online (Sandbox Code Playgroud) 在 Android 上使用 Kotlin 时,有一个特定的接口实现:从片段触发接口。考虑 Fragment 必须将 UI 操作传达给父 Activity 的常见场景。在 Java 中,我们将定义接口,创建它的“侦听器”实例,并在接口父项中实现/覆盖操作。创建一个监听器实例对我来说并不那么简单。经过一番谷歌搜索,我找到了一个实现示例,但我不明白它为什么有效。有一个更好的方法吗?为什么必须按照下面的方式实施?
class ImplementingFragment : Fragment(){
private lateinit var listener: FragmentEvent
private lateinit var vFab: FloatingActionButton
//Here is the key piece of code which triggers the interface which is befuddling to me
override fun onAttach(context: Context?) {
super.onAttach(context)
if(context is FragmentEvent) {
listener = context
}
}
//Notice the onClickListener using our interface listener member variable
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val v: View? …Run Code Online (Sandbox Code Playgroud) 我一生都无法在Kotlin或Android的Kotlin中实例化片段之外的接口。这是Java中的标准过程,其内容如下:
MyInterface mInterfaceListener = new MyInterface(this);
mInterfaceListener.invokeSomeGenericMethod();
Run Code Online (Sandbox Code Playgroud)
请注意,mInterfaceListener是指接口,而不是onCLickListener或类似的东西
如何在Kotlin中实例化接口?如何制作“监听器”并触发界面功能?
以下是我出于学习目的而在一个非常简单的应用程序中进行的一些尝试。注意变量mPresenterListener是一个接口
class QuoteActivity : QuoteContract.ViewOps, AppCompatActivity() {
private lateinit var vText: TextView
private lateinit var vFab: FloatingActionButton
private lateinit var mPresenterListener: QuoteContract.PresenterOperations
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mPresenterListener = this.mPresenterListener
vText=findViewById(R.id.main_quote)
vFab=findViewById(R.id.main_fab)
vFab.setOnClickListener{
mPresenterListener.onQuoteRequested()
}
}
override fun displayQuote(quote: String) {
vText.text = quote
}
}
Run Code Online (Sandbox Code Playgroud)
而我的主持人:
class QuotePresenter(private val viewListener: QuoteContract.ViewOps): QuoteContract.PresenterOperations {
private lateinit var modelListener: QuoteContract.ModelOperations
init {
modelListener = this.modelListener
}
override fun …Run Code Online (Sandbox Code Playgroud)