RxJava toSingle method cannot be resolved - android

The code is
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.schedulers.Schedulers;
public class BasePresenter {
protected <T> void subscribe(Observable<T> observable, Observer<T> observer) {
observable.subscribeOn(Schedulers.newThread())
.toSingle()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);
}
The problem was that I couldn't use AndroidSchedulers because Observable was 1.x version. I changed import's and now the problem is that i can't use .toSingle
I am just testing RxJava. so, please don't be angry if it is stupid question.

Related

WM-Factory no interface method getBackgroundExecutor()

I'm learning android development from Android_developer. while using CoroutinesWorker, I encountered a problem whilst working with Kotlin
Logcat
com.google.samples.apps.devbyteviewer E/WM-WorkerFactory: Could
not instantiate
com.google.samples.apps.devbyteviewer.work.RefreshDataWorker
java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at
androidx.work.WorkerFactory.createWorkerWithDefaultFallback(Worker
Factory.java:96)
at
androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:
244)
at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:136)
The Application class from where I instantiate workmanager.
Application class
package com.google.samples.apps.devbyteviewer
import android.app.Application
import androidx.work.*
import
com.google.samples.apps.devbyteviewer.work.RefreshDataWorker
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.concurrent.TimeUnit
As I have read in related posts, my worker class is a top level class and in an independent file.
Worker class
package com.google.samples.apps.devbyteviewer.work
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.google.samples.apps.devbyteviewer.database.getDatabase
import com.google.samples.apps.devbyteviewer.repository.VideosRepository
import retrofit2.HttpException
import timber.log.Timber
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
CoroutineWorker(appContext, params) {
override suspend fun doWork(): Result {
val database = getDatabase(applicationContext)
val repository = VideosRepository(database)
try {
repository.refreshVideos()
Timber.d("Work request for sync is run")
} catch (e: HttpException) {
return Result.retry()
}
return Result.success()
}
companion object {
/**
* Define a work name to uniquely identify this worker.
*/
const val WORK_NAME = "com.example.android.devbyteviewer.work.RefreshDataWorker"
}
}
I've had the same problem while working with WorkManager.
Pulling meaning from your post and the error message, this is very likely an import related issue. Check your Application dependencies.
Rather than:
implementation "android.arch.work:work-runtime-ktx:$work_version"
Use:
implementation "androidx.work:work-runtime-ktx:$work_version"

and its super classes have no public methods with the #Subscribe annotation with Kotlin and DI

I have checked all answers on the stack. But nothing helps. Might be problem in Kotlin + DI
So I got an exception that Eventbus for some reason cant initialize itself in presenter class. By debugger I see that method of initializing executed proper way from onCreate. I use the same code as I use in other classes (Java classes) and other works correctly. Could you please give an advice where might be an issue
Error
Caused by: org.greenrobot.eventbus.EventBusException: Subscriber class com.myapp.mvp.ui.myprofile.MyProfileActivity and its super classes have no public methods with the #Subscribe annotation
at org.greenrobot.eventbus.SubscriberMethodFinder.findSubscriberMethods(SubscriberMethodFinder.java:67)
at org.greenrobot.eventbus.EventBus.register(EventBus.java:140)
at com.myapp.mvp.ui.myprofile.MyProfileActivity.onCreate(MyProfileActivity.kt:67)
at android.app.Activity.performCreate(Activity.java:7981)
at android.app.Activity.performCreate(Activity.java:7970)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
My presenter class
import com.arellomobile.mvp.InjectViewState
import com.arellomobile.mvp.MvpPresenter
import com.myapp.UserProfileItemsList
import com.myapp.eventbus.VisitsEvent
import com.myapp.eventbus.UserEvent
import com.myapp.models.UserDescriptionModel
import com.myapp.mvp.model.interactor.myprofile.MyProfileInteractor
import com.myapp.utils.ActionsCountInfoCallback
import com.myapp.utils.UserCallback
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import java.util.ArrayList
import javax.inject.Inject
#InjectViewState
class MyProfilePresenter #Inject constructor(private val interactor: MyProfileInteractor) : MvpPresenter<MyProfileView>() {
private val userDescriptionList = ArrayList<UserDescriptionModel>()
override fun onFirstViewAttach() {
super.onFirstViewAttach()
setAllCurrentUserInfo()
setActionsCount()
}
fun setAllCurrentUserInfo() {
interactor.getAllCurrentUserInfo(UserCallback{ fsUser ->
viewState.setUserData(fsUser.name, fsUser.age, fsUser.country, fsUser.image)
userDescriptionList.addAll(UserProfileItemsList.initData(fsUser))
viewState.setList(userDescriptionList)
EventBus.getDefault().post(UserEvent(fsUser))
})
}
private fun setActionsCount() {
interactor.getActionsCountInfo(
ActionsCountInfoCallback{ visits, likes -> viewState.setActionsCount(visits, likes) })
}
#Subscribe
private fun updateActionsCount(event: VisitsEvent){
viewState.setActionsCount(event.getmVisits(), event.getmLikes())
}
fun registerSubscribers() {
if (!EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().register(this)
}
}
fun unsubscribe(){
EventBus.getDefault().unregister(this)
}
}
MyProfileActivity and its super classes have no public methods with the #Subscribe annotation
Emphasis mine. Remove the private from your function here:
#Subscribe
private fun updateActionsCount(event: VisitsEvent)

Lifecycle.addObserverUntilDestroy extension stopped working with AndroidX

I've been using following Kotlin extension to add my lifecycle observers:
fun Lifecycle.addObserverUntilDestroy(observer: LifecycleObserver) {
addObserver(observer)
addObserver(object : LifecycleObserver {
#OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy() {
removeObserver(this)
removeObserver(observer)
}
})
}
The idea was to automatically remove the observer when the Lifecycle is being destroyed.
So I can call it in Activity's onPostCreate (in this case a Java code but it is the same when calling from Kotlin):
ArchitectureComponentExtensions.addObserverUntilDestroy(getLifecycle(), myViewModel);
And have this code in my ViewModel (a custom one, not the on from Architecture Components):
#OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onViewDestroyed() {
// This is not being called anymore
}
But this stopped working after migrating from:
import android.arch.lifecycle.Lifecycle
import android.arch.lifecycle.LifecycleObserver
import android.arch.lifecycle.LifecycleOwner
import android.arch.lifecycle.OnLifecycleEvent
to:
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent
Any ideas why this is not working anymore?

Android Dagger 2 cannot resolve symbol builder()

I'm using Dagger 2 in Android Studio, but when try to create Component through DaggerMyComponent.builder().myModule(new MyModule()).build(), I always see the word "builder()" in red and it says "cannot resolve symbol builder".
I must say that I've cleaned and builted many times the project, even commenting the component instance and decommenting it after rebuild.
I must also say that I can inspect the DaggerMyComponent.class, and everything seems ok, in fact, I can import that class with no problem.
The example is shared on GithHub, at this link:
https://github.com/alessandroargentieri/LetsDagger2Together
I have two Classes: BClass and AClass which depends on the first one.
I have ABModule.class which is the factory method and ABComponent which is the component interface.
The DaggerABComponent is created into WholeApplication.class which extends Application.
package mawashi.alex.letsdagger2together.Application;
import android.app.Application;
import mawashi.alex.letsdagger2together.DaggerClasses.ABComponent;
import mawashi.alex.letsdagger2together.DaggerClasses.ABModule;
import mawashi.alex.letsdagger2together.DaggerClasses.DaggerABComponent;
public class WholeApplication extends Application {
static ABComponent component;
#Override
public void onCreate() {
super.onCreate();
//here is where builder() is not recognized
component = new DaggerABComponent.builder().aBModule(new ABModule()).build();
}
public static ABComponent getComponent(){
return component;
}
}
Module:
package mawashi.alex.letsdagger2together.DaggerClasses;
import dagger.Module;
import dagger.Provides;
import mawashi.alex.letsdagger2together.Model.AClass;
import mawashi.alex.letsdagger2together.Model.BClass;
#Module
public class ABModule {
#Provides
public BClass provideBClass(){
return new BClass("xxx");
}
#Provides
public AClass provideAClass(BClass bClass){
return new AClass(bClass);
}
}
Component:
package mawashi.alex.letsdagger2together.DaggerClasses;
import dagger.Component;
import mawashi.alex.letsdagger2together.MainActivity;
#Component (modules = {ABModule.class})
public interface ABComponent {
public void inject(MainActivity mainActivity);
}
Classes which are to be injected:
package mawashi.alex.letsdagger2together.Model;
public class BClass {
private String xfactor;
public BClass(String xfactor){
this.xfactor = xfactor;
}
public String getXfactor(){
return xfactor;
}
}
package mawashi.alex.letsdagger2together.Model;
public class AClass {
private BClass b;
public AClass(BClass b){
this.b = b;
}
public String getYfactor(){
return "Y-" + b.getXfactor() + "-Y";
}
}
Place where to inject AClass and BClass:
package mawashi.alex.letsdagger2together;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
import javax.inject.Inject;
import mawashi.alex.letsdagger2together.Application.WholeApplication;
import mawashi.alex.letsdagger2together.DaggerClasses.ABModule;
import mawashi.alex.letsdagger2together.DaggerClasses.DaggerABComponent;
import mawashi.alex.letsdagger2together.Model.AClass;
public class MainActivity extends AppCompatActivity {
#Inject AClass a;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WholeApplication.getComponent().inject(this);
Toast.makeText(this, a.getYfactor(),Toast.LENGTH_LONG).show();
}
}
If anyone knows what I mistake it would be very nice to me. Thanks to everybody.
Oh, I've figured it out.
You added this line:
component = new DaggerABComponent.builder().aBModule(new ABModule()).build();
And it should be this line:
component = DaggerABComponent.builder().aBModule(new ABModule()).build();
So just remove new and then it'll work.
All fields with #Inject annotation must be public:
#Inject public AClass a; in your Activity

How to inject dependencies into a Robolectric Test-class using RoboGuice

I want to start using Robolectric and RoboGuice in my Android-Apps. While I make satisfactory progress using Robolectric I am stuck using RoboGuice. I created a small Android-App for experimenting. It is only one Activity, injecting a Button and setting its OnClickListener.
In the related Test-Class I want to Inject this Activity, to be able to test the Button. I tried a lot of things I found all over the internet, but none of these worked, so I give it a go here.
Here is some code:
MainActivity.java:
package com.example.TrialApp;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import roboguice.activity.RoboActivity;
import roboguice.inject.InjectView;
public class MainActivity extends RoboActivity implements View.OnClickListener {
#InjectView(R.id.main_LoginButton) private Button loginButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
loginButton.setOnClickListener(this);
}
#Override
public void onClick(View view) {
SharedPreferences.Editor editor;
if (view.getId() == R.id.main_Login_Button)
Log.i("Login-Button pressed... ", "");
}
}
CustomRobolectricTestRunner.java:
package com.example.TrialApp;
import com.xtremelabs.robolectric.RobolectricTestRunner;
import org.junit.runners.model.InitializationError;
import java.io.File;
public class CustomRobolectricTestRunner extends RobolectricTestRunner {
public CustomRobolectricTestRunner(Class testClass) throws InitializationError {
// defaults to "AndroidManifest.xml", "res" in the current directory
super(testClass, new File("TrialApp"));
}
}
MainActivity_Test.java:
package com.example.TrialApp;
import com.google.inject.Inject;
import com.xtremelabs.robolectric.Robolectric;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertNotNull;
#RunWith(CustomRobolectricTestRunner.class)
public class MainActivity_Test {
#Inject MainActivity mainActivity;
#Inject ClassWithoutAName classWithoutAName;
#Before
public void setUp() {
}
#Test
public void mainActivityShouldNotBeNull() {
assertNotNull(mainActivity);
}
#Test
public void classWithoutANameShouldNotBeNull() {
assertNotNull(classWithoutAName);
}
}
classWithoutAName is just a non-Activity-class with no content. I added just for injecting a non-Activity-class.
Running the Test-Class both tests fail giving the following errors:
java.lang.AssertionError
at com.example.TrialApp.MainActivity_Test.mainActivityShouldNotBeNull(MainActivity_Test.java:33) <8 internal calls>
at com.xtremelabs.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:288) <16 internal calls>
and
java.lang.AssertionError
at com.example.TrialApp.MainActivity_Test.classWithoutANameShouldNotBeNull(MainActivity_Test.java:38) <8 internal calls>
at com.xtremelabs.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:288) <16 internal calls>
Obviously something is missing. Injecting in MainActivity works fine, and the app is running.
Why is the same pattern of injecting dependencies in a Robolectric-Testclass not working? Where is the missing link?
Thank you
After reading some more articles and threads I found a partial solution. I still haven't found a way to inject UI-elements in a testclass, but I found out, how to inject non-UI-elements in a testclass. The trick is to implement a "RobolectricTestModule" extending the AbstractModule. The bindings made in the modules declared in the roboguice.xml are not present in the test-environment, so we need to declare the bindings for the test-environment in this extra-module. In the customized Testrunner we replace the DefaultRoboModule with the new RobolectricTestModule.
ClassWithoutAName.java:
package com.example.TrialApp;
public class ClassWithoutAName {
private String string;
public ClassWithoutAName(String string) {
this.string = string;
}
public String getString() {
return string;
}
}
ClassWithoutANameProvider.java
package com.example.TrialApp.GuiceModules;
import com.example.TrialApp.ClassWithoutAName;
import com.google.inject.Provider;
public class ClassWithoutANameProvider implements Provider<ClassWithoutAName> {
#Override
public ClassWithoutAName get() {
return new ClassWithoutAName("testString");
}
}
ClassWithOutANameModule.java
package com.example.TrialApp.GuiceModules;
import com.example.TrialApp.ClassWithoutAName;
import com.google.inject.AbstractModule;
public class ClassWithOutANameModule extends AbstractModule {
#Override
protected void configure() {
bind(ClassWithoutAName.class).toProvider(ClassWithoutANameProvider.class);
}
}
RobolectricTestModule.java
package com.example.TrialApp.GuiceModules;
import com.example.TrialApp.WeirdThings;
import com.google.inject.AbstractModule;
public class RobolectricTestModule extends AbstractModule {
#Override
protected void configure() {
bind(ClassWithoutAName.class).toProvider(ClassWithoutANameProvider.class);
}
}
CustomRobolectricTestRunner.java
package com.example.TrialApp;
import android.app.Application;
import com.example.TrialApp.GuiceModules.RobolectricTestModule;
import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.RobolectricTestRunner;
import org.junit.runners.model.InitializationError;
import roboguice.RoboGuice;
import java.io.File;
public class CustomRobolectricTestRunner extends RobolectricTestRunner {
public CustomRobolectricTestRunner(Class testClass) throws InitializationError {
// defaults to "AndroidManifest.xml", "res" in the current directory
super(testClass, new File("TrialApp"));
}
#Override
public void prepareTest(Object test) {
Application application = (Application) Robolectric.application;
RoboGuice.setBaseApplicationInjector(application, RoboGuice.DEFAULT_STAGE,
RoboGuice.newDefaultRoboModule(application), new RobolectricTestModule());
RoboGuice.getInjector(application).injectMembers(test);
}
}
Thats it for the non-UI-Elements.

Categories

Resources