Не получаете ответ при вызове API с помощью MVVM и Retrofit? - PullRequest
1 голос
/ 12 апреля 2020

Я пытаюсь использовать MVVM, Retrofit, Dagger в своем приложении, поэтому в начале я использовал ArrayList только для отображения моих данных из viewModel в View, и это сработало, теперь я использую все это, но Я получаю сообщение об ошибке, я не получаю сообщение об ошибке, мне это не кажется понятным.

Я использую скрипт php, который возвращает ответ 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();
    }


}

Вот мой ContractService:

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")
        }
        });

    }
}

Я ничего не получаю.

Я ожидаю получить следующее:

enter image description here

Вот что я получаю:

enter image description 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)

Любая помощь будет высоко ценится, потому что я попробовал это в проекте, а затем я попытался сделать новый потому что я думал, что я не все правильно настроил, но похоже, что он не работает.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 13 апреля 2020

Попробуйте использовать adb reverse tcp:80 tcp:80. Это позволяет эмулятору получить доступ к порту 80 на вашем P C (хост)

1 голос
/ 12 апреля 2020

Итак, я нашел решение своей проблемы, мне не пришлось использовать localhost в моем URL-адресе BASE, мне пришлось вызывать IP-адрес. Причина в том, что когда вы вызываете localhost, он относится к эмулятору android, а не P C, поэтому для настройки API на вашем локальном компьютере p c используйте его 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();
}

}
...