我目前正在尝试使用来自改造和 Okhttp 的 API 请求在架构组件中实现新的 ViewModel,一切正常,但我不知道如何将错误响应从改造传递到片段中的观察者,然后LiveDataReactiveStreams.fromPublisher上游传递给片段中的观察者。这是我到目前为止所拥有的:
public class ShowListViewModel extends AndroidViewModel {
private final ClientAdapter clientAdapter;
private LiveData<List<Show>> shows;
public ShowListViewModel(Application application) {
super(application);
clientAdapter = new ClientAdapter(getApplication().getApplicationContext());
loadShows();
}
public LiveData<List<Show>> getShows() {
if (shows == null) {
shows = new MutableLiveData<>();
}
return shows;
}
void loadShows() {
shows = LiveDataReactiveStreams.fromPublisher(Observable.fromIterable(ShowsUtil.loadsIds())
.subscribeOn(Schedulers.io())
.flatMap(clientAdapter::getShowWithNextEpisode)
.observeOn(Schedulers.computation())
.toSortedList(new ShowsUtil.ShowComparator())
.observeOn(AndroidSchedulers.mainThread())
.toFlowable());
}
Run Code Online (Sandbox Code Playgroud)
在片段中,我在 OnCreate 中使用以下内容设置了 viewModel:
ShowListViewModel model = ViewModelProviders.of(this).get(ShowListViewModel.class);
model.getShows().observe(this, shows -> {
if (shows == null || …Run Code Online (Sandbox Code Playgroud) 我正在开发一个使用架构组件的项目,我有一个关于正确使用 LifecycleObserver 模式的问题。
\n\n问题是:我什么时候应该取消注册观察者以及如果没有调用取消注册会发生什么?
\n\n简单直接的用例可以如下所示:
\n\npublic class MyActivity extends LifecycleActivity {\n\n @Override\n protected void onCreate(@Nullable Bundle savedInstanceState) {\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0 super.onCreate(savedInstanceState);\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0 ...\n getLifecycle().addObserver(someLifecycleObserver);\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0}\n\n @Override\n protected void onDestroy() {\n super.onDestroy();\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0 ...\n getLifecycle().removeObserver(someLifecycleObserver);\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0}\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这可能是不费吹灰之力并且正确使用的。但随着观察者的增多,就会出现很多这样的样板代码。
\n\n好的,现在让我们将 Dagger 添加到其中。我们可以让 Dagger 将这个“someLifecycleObserver”对象注入到 Activity(以及片段等其他地方)。
\n\n简单的 Dagger 模块如下所示:
\n\n@Module\npublic class ConfigurationManagerModule {\n\n @Provides\n @ActivityScope\n SomeManager provideSomeManager(final AppCompatActivity activity, final Object otherDependency) {\n return new SomeManager(activity, otherDependency);\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n然后在Activity中我们需要注册/注销观察者。但如果我们可以取消注册并让 Dagger 来完成呢?
\n\n @Provides\n @ActivityScope\n SomeManager provideSomeManager(final AppCompatActivity activity, final Object otherDependency) {\n …Run Code Online (Sandbox Code Playgroud) 使用@Relation 注释。我可以使用以下方法查询一对多关系:
@Dao
public interface PostDao {
@Query("SELECT * FROM post")
List<PostWithComments> getPostWithComments();
}
Run Code Online (Sandbox Code Playgroud)
这里是实体
@Entity
public class Post {
@PrimrayKey
private int id;
private String title;
private String content;
}
@Entity
public class Comment {
@PrimrayKey
private int id;
private int post_id;
private String content;
private String status;
}
public class PostWithComments {
@Embedded
public Post post;
@Relation(parentColumn = "id", entityColumn = "post_id", entity = Comment.class)
public List<Comment> comments;
}
Run Code Online (Sandbox Code Playgroud)
我想得到所有有评论的帖子,status = approved但我不确定房间是如何处理的。我尝试了以下方法:
@Dao
public interface PostDao …Run Code Online (Sandbox Code Playgroud) 我想用 MVVM 架构在 android 中创建一个自定义视图。首先,我想问一下,ViewModel 是否与自定义视图完美配合,因为它可以在活动或片段的情况下工作?我们可以在自定义视图中从 ViewModel 提供者获取 ViewModel 吗?
如果我需要制作一个单独的自定义视图,正确的方法是什么?
我正在使用navigation component和BottomNavigationView,我面临一个问题,那就是当我从fragment1>2>5>4>3转到时,当我按下后退按钮时,我得到fragment1。我知道这是默认行为,但我不想要这个,我想保存它们,backstack所以当我按下后退按钮时,它应该转到fragment4 而不是 1。我一直在尝试和搜索,但找不到任何解决方案。我可以把fragment手动进backstack的kotlin?
我的代码:
活动_main.xml
<androidx.constraintlayout.widget.ConstraintLayout
.......................
.......................>
<androidx.appcompat.widget.Toolbar
................
................/>
<fragment
android:id="@+id/app_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:navGraph="@navigation/app_nav"
..............
............../>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/app_bottom_nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/white_grey_border_bottom"
app:menu="@menu/bottom_nav_menu"
app:labelVisibilityMode="unlabeled"
...........
.........../>
</androidx.constraintlayout.widget.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)
app_nav.xml
<navigation
...........
...........
android:id="@+id/app_nav"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.example.instagram_clone.ui.HomeFragment"
android:label="HomeFragment"
tools:layout="@layout/fragment_home"/>
.............
.............
.............
.............
</navigation>
Run Code Online (Sandbox Code Playgroud)
主活动.kt
class MainActivity : AppCompatActivity()
{
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
val binding = …Run Code Online (Sandbox Code Playgroud) android android-fragments bottomnavigationview android-architecture-components android-jetpack
我正在根据使用 BroadcastReceiver 启动的Worker的条件向用户发送每日通知。从Worker我只需要context发送通知。
NotificationCompat.Builder(context, CHANNEL_ID).apply {
setContentTitle(...)
setContentText(...)
setContentIntent(pendingIntent(context))
}.build()
Run Code Online (Sandbox Code Playgroud)
如何PendingIntent使用导航组件创建启动特定片段?
我试过这个:
fun pendingIntent(context: Context): PendingIntent {
val navController = NavController(context.applicationContext)
navController.setGraph(R.navigation.your_navigation)
return navController.createDeepLink()
.setDestination(R.id.yourFragment)
.createPendingIntent()
}
Run Code Online (Sandbox Code Playgroud)
但我得到以下例外:
Caused by: java.lang.RuntimeException: Exception inflating package.name:navigation/your_navigation line 7
at androidx.navigation.NavInflater.inflate(NavInflater.java:90)
at androidx.navigation.NavController.setGraph(NavController.java:425)
at androidx.navigation.NavController.setGraph(NavController.java:407)
at
......
at package.name.Worker.doWork(Worker.kt:15)
at androidx.work.Worker$1.run(Worker.java:85)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: java.lang.IllegalStateException: Could not find Navigator with name "fragment". You must call NavController.addNavigator() for each navigation type. …Run Code Online (Sandbox Code Playgroud) java android kotlin android-architecture-components android-workmanager
我只是 kotlin 协程的新手。我刚刚创建了用于测试实时数据的新项目,但我无法观察到数据更改。我不明白 livedata 的概念。什么时候触发?因为当我观察 ROOM 数据库时(不是协程方式。我使用了 MutableLiveData)它工作得很好。每当数据发生变化时,总是会触发观察者。
我只是想清理和现代代码。我的期望:当我单击 btnLogin 按钮时(当用户使用另一个帐户登录时或者您可以说数据更改时)必须触发 livedata。
这是我的例子:
改造界面:
interface RetroMainClient {
@POST("login.php")
suspend fun login(@Body model: UserLoginModel): Response<UserLoginModel>
companion object {
val getApi: RetroMainClient by lazy {
Retrofit.Builder().baseUrl("https://example.com/")
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().create())).build()
.create(RetroMainClient::class.java)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的存储库:
class Repository {
suspend fun getLoginApi(model: UserLoginModel) = RetroMainClient.getApi.login(model)
}
Run Code Online (Sandbox Code Playgroud)
我的视图模型:
class MainViewModel : ViewModel() {
fun login(model: UserLoginModel) = liveData(IO) {
try {
emit(Repository().getLoginApi(model))
} catch (e: Exception) {
Log.e("exception", "${e.message}")
}
}
}
Run Code Online (Sandbox Code Playgroud)
和我的主要活动:
class MainActivity : AppCompatActivity() …Run Code Online (Sandbox Code Playgroud) android kotlin android-livedata android-architecture-components kotlin-coroutines
我目前正在研究Android Room with a View示例应用程序,这里提供完整的源代码。在这个项目中,定义了一个WordViewModel类型AndroidViewModel:
class WordViewModel(application: Application) : AndroidViewModel(application)
Run Code Online (Sandbox Code Playgroud)
请注意构造函数如何要求Application传入一个实例。然而,当我检查 时MainActivity,WordViewModel检索了 而不传入
Application实例:
// Get a new or existing ViewModel from the ViewModelProvider.
mWordViewModel = new ViewModelProvider(this).get(WordViewModel.class);
Run Code Online (Sandbox Code Playgroud)
这怎么可能,如何在WordViewModel不传入Application实例和不使用自定义工厂的情况下检索?
我曾尝试阅读此内容,但它并没有解决我的问题
所以我使用此代码导航到下一个目的地
val nextDirection = CreateEventNameFragmentDirections.actionToCreateEventType(userKM, newEvent)
findNavController().navigate(nextDirection)
Run Code Online (Sandbox Code Playgroud)
但它在我错误旋转设备后崩溃
java.lang.IllegalStateException: 没有当前导航节点
我用这个更新gradle
Run Code Online (Sandbox Code Playgroud)implementation 'android.arch.navigation:navigation-fragment-ktx:2.2.1' implementation 'android.arch.navigation:navigation-ui-ktx:2.2.1'
但它仍然不起作用,它仍然崩溃。我该怎么办 ?这是我的主要活动
class MainActivity : AppCompatActivity(), NavController.OnDestinationChangedListener {
private lateinit var navController : NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Initial Setup views
navController = Navigation.findNavController(this,R.id.nav_host_fragment)
setupBottomNavMenu()
setupActionBar()
// Add Listeners
navController.addOnDestinationChangedListener(this)
}
private fun setupBottomNavMenu() {
bottom_nav.setupWithNavController(navController)
}
private fun setupActionBar() {
generalToolbar.title = ""
searchToolbar.title = ""
searchWithBackButtonToolbar.title = ""
// set up top hierarchy destination
val appBarConfiguration …Run Code Online (Sandbox Code Playgroud) android android-navigation android-architecture-components android-architecture-navigation android-jetpack-navigation
我正在使用 Android 导航组件,如果我在第二个片段中,我有一个包含三个片段的活动,并旋转屏幕强制活动重新启动导航返回到开始目的地。
当活动重新启动时,navhostFragment 不应该保留图形的状态吗?
或者这里发生了什么默认行为?
即使添加“有效”,我也不想添加以下内容
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
Run Code Online (Sandbox Code Playgroud)
因为不想自己处理方向变化,希望系统正常处理,还保留导航状态
如果有帮助,我会提供一些我的代码
在活动中我使用 navController.setGraph() 所以我可以像这样将数据传递到开始目的地
navController = Navigation.findNavController(
this,
R.id.nav_host_fragment
)
setSupportActionBar(findViewById(R.id.toolbar))
appBarConfiguration = AppBarConfiguration.Builder(navController.graph).build()
supportActionBar?.setDisplayHomeAsUpEnabled(true)
intent.putExtra("EXTRA_KEY","some_data")
navController.setGraph(R.navigation.nav_graph,intent.extras)
Run Code Online (Sandbox Code Playgroud)
我使用这个从片段导航到片段
navController.navigate(FirstFragmentDirections.actionFirstFragmentToSecondFragment())
Run Code Online (Sandbox Code Playgroud)
这是 nav_graph 中的代码
<fragment
android:id="@+id/FirstFragment"
android:name="com.example.app.presentation.ui.FirstFragment"
android:label="FirstFragment" >
<action
android:id="@+id/action_FirstFragment_to_secondFragment"
app:destination="@id/secondFragment"
app:enterAnim="@anim/enter_from_right"
app:exitAnim="@anim/exit_to_left"
app:popEnterAnim="@anim/enter_from_left"
app:popExitAnim="@anim/exit_to_right"
/>
</fragment>
<fragment
android:id="@+id/secondFragment"
android:name="com.example.app.presentation.ui.secondFragment"
android:label="secondFragment"
tools:layout="@layout/fragment_second" />
Run Code Online (Sandbox Code Playgroud)
感谢您的帮助
android onconfigurationchanged android-architecture-components android-jetpack android-architecture-navigation
android ×10
android-architecture-components ×10
android-architecture-navigation ×2
kotlin ×2
android-room ×1
java ×1
retrofit2 ×1
rx-java2 ×1