I am learning design patterns from Head First Design Patterns and a principle I came across is to "code to interface". Now I want to apply this principle in my Android app, which includes lots of API calls. I am using Retrofit for network calls.
I have applied this principle considering some scenario something like this:
- Suppose in the future I need to shift from Retrofit to Volley or any other networking library.
- I created an interface with a method to
getData
from the server and created a class which implements that interface. The implemented method includes the Retrofit code togetData
from the server. - Now in the future, if I want to use Volley, I'll create a new class implementing the interface and with Volley code to retrieve data from the server.
Interface
public interface NetworkCallsApi {
String getDataFromServer(Activity activity,String url,String Callback);
}
Retrofit Implementation
public class NetworkCallsRetrofitImpl implements NetworkCallsApi{
private Retrofit retrofit;
@Override
public String getDataFromServer(Activity activity, String url, String Callback) {
retrofit = new Retrofit.Builder()
.baseUrl(StringConstants.ROOT_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitApi apiCalls = retrofit.create(RetrofitApi.class);
Call<ResponseBody> call = apiCalls.getDataFromServer(url);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
return null;
}
}
ServiceCalls.java
public class ServiceCalls {
public static ServiceCalls serviceCalls;
public NetworkCallsApi networkCallsimpl;
public static ServiceCalls getInstance(){
if(serviceCalls == null){
serviceCalls = new ServiceCalls();
}
return serviceCalls;
}
public void setNetworkCallsimpl(NetworkCallsApi networkCallsimpl) {
this.networkCallsimpl = networkCallsimpl;
}
public String getDataFromServer(Activity activity, String url, String callback){
networkCallsimpl.getDataFromServer(activity,url,callback);
return null;
}
}
MainFragment:
public class StatusFragment extends Fragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Setting the implementation
ServiceCalls.getInstance().setNetworkCallsimpl(new NetworkCallsRetrofitImpl());
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_pnr_status,container,false);
try{
init();
}catch(Exception e){}
return view;
}
private void init() {
ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
setUrlKeysAndValues();
ServiceCalls.getInstance().getDataFromServer(getActivity()
,Utils.getInstance().buildUrl(urlKeys,urlValues),"onResponse");
}
});
}
}
Have I correctly applied that principle? If not, what changes do I need to make? In onCreate
of MainFragment
, I am hardcoding the implementation. How can the interface design pattern be better applied in this scenario?