使用 MVVM 和 Retrofit 调用我的 api 时没有得到我的回应?
Not getting my response when calling my api using MVVM and Retrofit?
我正在尝试在我的应用程序中使用 MVVM、Retrofit、Dagger,所以在开始时我只使用 ArrayList 将我的数据从 viewModel 显示到 View 并且它有效,现在我全部使用它, 但我收到错误,我没有收到错误,我似乎不清楚。
我在我的本地机器上使用 php 脚本 returns 一个 JSON 响应。
我想这里有很多代码要提供,所以这是我的 ContractListViewModel:
public class ContractsListViewModel extends ViewModel {
public MutableLiveData<List<ContractModel>> contractList = new MutableLiveData<List<ContractModel>>();
MutableLiveData<Boolean> isLoading= new MutableLiveData<Boolean>();
MutableLiveData<Boolean> error= new MutableLiveData<Boolean>();
@Inject
ContractService contractService;
CompositeDisposable disposable = new CompositeDisposable();
public ContractsListViewModel(){
super();
DaggerContractApiComponent.create().inject(this);
}
public void call(){
fetchContracts();
}
public void fetchContracts(){
isLoading.setValue(true);
disposable.add(
contractService.getContracts()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<List<ContractModel>>() {
@Override
public void onSuccess(List<ContractModel> friendsModels) {
isLoading.setValue(false);
error.setValue(false);
contractList.setValue(friendsModels);
}
@Override
public void onError(Throwable e) {
error.setValue(true);
isLoading.setValue(false);
e.printStackTrace();
}
})
);
}
@Override
protected void onCleared(){
super.onCleared();
disposable.clear();
}
}
这是我的合同服务:
public class ContractService {
public static ContractService instance;
@Inject
public ContractApi api;
private ContractService(){
DaggerContractApiComponent.create().inject(this);
}
public static ContractService getInstance(){
if(instance == null){
instance = new ContractService();
}
return instance;
}
public Single<List<ContractModel>> getContracts(){
return api.getContractList();
}
}
这是我的 ContratApiComponent(用于注入):
@Component(modules = { ApiModule.class})
public interface ContractApiComponent {
public void inject(ContractService contractService);
public void inject(ContractsListViewModel contractListViewModel);
}
这是我的 ContratctApi:
public interface ContractApi {
@GET("contrats.php")
Single<List<ContractModel>> getContractList();
}
这是我的 ApiModule:
@Module
public class ApiModule {
public static String BASE_URL = "http://localhost/newconceptsphp/";
@Provides
public ContractApi provideContractApi(){
return new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(ContractApi.class);
}
@Provides
public ContractService provideContractService(){
return ContractService.getInstance();
}
}
这是我的 MainActivity:
public class MainActivity extends AppCompatActivity {
ContractsListViewModel contractsListViewModel;
@BindView(R.id.newContractBtn)
Button newContractBtn;
RecyclerView.Adapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding main = DataBindingUtil.setContentView(this, R.layout.activity_main);
ButterKnife.bind(this);
main.contractList.setLayoutManager(new LinearLayoutManager(this));
contractsListViewModel = ViewModelProviders.of(this).get(ContractsListViewModel.class);
contractsListViewModel.call();
contractsListViewModel.contractList.observe(this,contractModels -> {
if(contractModels != null){
adapter = new ContractListAdapter(MainActivity.this, contractModels);
main.contractList.setAdapter(adapter);
}else {
Log.d("TAG", "Nothing is here")
}
});
}
}
我一无所获。
我希望得到的是:
这是我得到的:
这是我得到的错误:
2020-04-12 17:53:08.308 27128-27128/com.example.cosysimulation W/System.err: java.net.ConnectException: Failed to connect to localhost/127.0.0.1:80
2020-04-12 17:53:08.309 27128-27128/com.example.cosysimulation W/System.err: at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:225)
2020-04-12 17:53:08.309 27128-27128/com.example.cosysimulation W/System.err: at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:149)
2020-04-12 17:53:08.310 27128-27128/com.example.cosysimulation W/System.err: at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:192)
任何帮助将不胜感激,因为我在一个项目中尝试过这个,然后我尝试制作一个新的,因为我认为我显然没有正确设置所有内容,但它似乎不起作用。
谢谢。
所以我找到了解决问题的方法,我不得不在我的 BASE 中不使用本地主机 url,我不得不调用 IP 地址,原因是当你调用本地主机时,它指的是android 模拟器而不是 PC,所以为了在你的本地 pc 机器上定位 api,使用它的 IP:
@Module
public class ApiModule {
public static String BASE_URL = "http://***IP ADRRSS HERE INSTEAD OF LOCALHOST***/newconceptsphp/";
@Provides
public ContractApi provideContractApi(){
return new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(ContractApi.class);
}
@Provides
public ContractService provideContractService(){
return ContractService.getInstance();
}
}
尝试使用 adb reverse tcp:80 tcp:80
。这允许模拟器访问您PC(主机)上的端口80
我正在尝试在我的应用程序中使用 MVVM、Retrofit、Dagger,所以在开始时我只使用 ArrayList 将我的数据从 viewModel 显示到 View 并且它有效,现在我全部使用它, 但我收到错误,我没有收到错误,我似乎不清楚。
我在我的本地机器上使用 php 脚本 returns 一个 JSON 响应。
我想这里有很多代码要提供,所以这是我的 ContractListViewModel:
public class ContractsListViewModel extends ViewModel {
public MutableLiveData<List<ContractModel>> contractList = new MutableLiveData<List<ContractModel>>();
MutableLiveData<Boolean> isLoading= new MutableLiveData<Boolean>();
MutableLiveData<Boolean> error= new MutableLiveData<Boolean>();
@Inject
ContractService contractService;
CompositeDisposable disposable = new CompositeDisposable();
public ContractsListViewModel(){
super();
DaggerContractApiComponent.create().inject(this);
}
public void call(){
fetchContracts();
}
public void fetchContracts(){
isLoading.setValue(true);
disposable.add(
contractService.getContracts()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<List<ContractModel>>() {
@Override
public void onSuccess(List<ContractModel> friendsModels) {
isLoading.setValue(false);
error.setValue(false);
contractList.setValue(friendsModels);
}
@Override
public void onError(Throwable e) {
error.setValue(true);
isLoading.setValue(false);
e.printStackTrace();
}
})
);
}
@Override
protected void onCleared(){
super.onCleared();
disposable.clear();
}
}
这是我的合同服务:
public class ContractService {
public static ContractService instance;
@Inject
public ContractApi api;
private ContractService(){
DaggerContractApiComponent.create().inject(this);
}
public static ContractService getInstance(){
if(instance == null){
instance = new ContractService();
}
return instance;
}
public Single<List<ContractModel>> getContracts(){
return api.getContractList();
}
}
这是我的 ContratApiComponent(用于注入):
@Component(modules = { ApiModule.class})
public interface ContractApiComponent {
public void inject(ContractService contractService);
public void inject(ContractsListViewModel contractListViewModel);
}
这是我的 ContratctApi:
public interface ContractApi {
@GET("contrats.php")
Single<List<ContractModel>> getContractList();
}
这是我的 ApiModule:
@Module
public class ApiModule {
public static String BASE_URL = "http://localhost/newconceptsphp/";
@Provides
public ContractApi provideContractApi(){
return new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(ContractApi.class);
}
@Provides
public ContractService provideContractService(){
return ContractService.getInstance();
}
}
这是我的 MainActivity:
public class MainActivity extends AppCompatActivity {
ContractsListViewModel contractsListViewModel;
@BindView(R.id.newContractBtn)
Button newContractBtn;
RecyclerView.Adapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding main = DataBindingUtil.setContentView(this, R.layout.activity_main);
ButterKnife.bind(this);
main.contractList.setLayoutManager(new LinearLayoutManager(this));
contractsListViewModel = ViewModelProviders.of(this).get(ContractsListViewModel.class);
contractsListViewModel.call();
contractsListViewModel.contractList.observe(this,contractModels -> {
if(contractModels != null){
adapter = new ContractListAdapter(MainActivity.this, contractModels);
main.contractList.setAdapter(adapter);
}else {
Log.d("TAG", "Nothing is here")
}
});
}
}
我一无所获。
我希望得到的是:
这是我得到的:
这是我得到的错误:
2020-04-12 17:53:08.308 27128-27128/com.example.cosysimulation W/System.err: java.net.ConnectException: Failed to connect to localhost/127.0.0.1:80
2020-04-12 17:53:08.309 27128-27128/com.example.cosysimulation W/System.err: at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:225)
2020-04-12 17:53:08.309 27128-27128/com.example.cosysimulation W/System.err: at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:149)
2020-04-12 17:53:08.310 27128-27128/com.example.cosysimulation W/System.err: at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:192)
任何帮助将不胜感激,因为我在一个项目中尝试过这个,然后我尝试制作一个新的,因为我认为我显然没有正确设置所有内容,但它似乎不起作用。
谢谢。
所以我找到了解决问题的方法,我不得不在我的 BASE 中不使用本地主机 url,我不得不调用 IP 地址,原因是当你调用本地主机时,它指的是android 模拟器而不是 PC,所以为了在你的本地 pc 机器上定位 api,使用它的 IP:
@Module
public class ApiModule {
public static String BASE_URL = "http://***IP ADRRSS HERE INSTEAD OF LOCALHOST***/newconceptsphp/";
@Provides
public ContractApi provideContractApi(){
return new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(ContractApi.class);
}
@Provides
public ContractService provideContractService(){
return ContractService.getInstance();
}
}
尝试使用 adb reverse tcp:80 tcp:80
。这允许模拟器访问您PC(主机)上的端口80