Android中如何复用Retrofit代码?请求方法抽离复用方案问询
Absolutely! You can totally extract that repetitive network call logic into a separate class to reuse it across all your Activities. This not only eliminates duplicate code but also keeps your Activities focused on UI-related tasks (following the Single Responsibility Principle). Here are two practical approaches tailored to your current Retrofit setup:
1. Basic Approach: Repository Pattern with Custom Callback
First, let's clean up your original LeafAPI interface by moving the Retrofit/OkHttpClient initialization out of the interface (placing static instances directly in an interface isn't ideal practice):
public interface LeafAPI { @GET("someController/serviceName") Call<ArrayList<UserDetails>> getUserList(); }
Next, create a dedicated ApiClient class to handle Retrofit instance creation (this centralizes configuration and makes it easy to update later):
public class ApiClient { private static Retrofit retrofit = null; private static OkHttpClient okHttpClient; // Reusable OkHttpClient with logging and timeouts private static OkHttpClient getOkHttpClient() { if (okHttpClient == null) { HttpLoggingInterceptor logging = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC); okHttpClient = new OkHttpClient.Builder() .addInterceptor(logging) .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .build(); } return okHttpClient; } // Get the main Retrofit instance public static Retrofit getRetrofitInstance() { if (retrofit == null) { retrofit = new Retrofit.Builder() .baseUrl(ConstantValues.BaseUrl) .addConverterFactory(GsonConverterFactory.create()) .client(getOkHttpClient()) .build(); } return retrofit; } // Optional: Get the scalar-enabled Retrofit instance if you need it public static Retrofit getRetrofitScrInstance() { return new Retrofit.Builder() .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .baseUrl(ConstantValues.BaseUrl) .client(getOkHttpClient()) .build(); } }
Create a custom callback interface to pass results back to your Activities:
public interface UserCallback { void onUserListSuccess(ArrayList<UserDetails> userList); void onUserListFailure(String errorMessage); }
Now, build a UserRepository class to encapsulate all user-related network logic:
public class UserRepository { private LeafAPI leafAPI; public UserRepository() { leafAPI = ApiClient.getRetrofitInstance().create(LeafAPI.class); } // Reusable method to fetch user list public void fetchUserList(final UserCallback callback) { Call<ArrayList<UserDetails>> call = leafAPI.getUserList(); call.enqueue(new Callback<ArrayList<UserDetails>>() { @Override public void onResponse(Call<ArrayList<UserDetails>> call, retrofit2.Response<ArrayList<UserDetails>> response) { if (response.isSuccessful() && response.body() != null) { callback.onUserListSuccess(response.body()); } else { callback.onUserListFailure("Failed to load users: " + response.message()); } } @Override public void onFailure(Call<ArrayList<UserDetails>> call, Throwable t) { callback.onUserListFailure("Network error: " + t.getMessage()); } }); } }
Usage in Any Activity
Now you can reuse this logic in any Activity with just a few lines:
private void getUserDetails() { UserRepository userRepo = new UserRepository(); userRepo.fetchUserList(new UserCallback() { @Override public void onUserListSuccess(ArrayList<UserDetails> userList) { // Process and display user list in your UI } @Override public void onUserListFailure(String errorMessage) { // Show error message to the user } }); }
2. Advanced Approach: ViewModel + LiveData (Jetpack)
If you're using Android Jetpack, this approach is even better—it avoids memory leaks (since ViewModels survive configuration changes) and keeps your UI code cleaner.
First, create a UserViewModel that holds the data state:
import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; public class UserViewModel extends ViewModel { private final MutableLiveData<ArrayList<UserDetails>> userListLiveData = new MutableLiveData<>(); private final MutableLiveData<String> errorLiveData = new MutableLiveData<>(); private final UserRepository userRepository; public UserViewModel() { userRepository = new UserRepository(); } public void fetchUserList() { userRepository.fetchUserList(new UserCallback() { @Override public void onUserListSuccess(ArrayList<UserDetails> userList) { userListLiveData.postValue(userList); // Update data on main thread } @Override public void onUserListFailure(String errorMessage) { errorLiveData.postValue(errorMessage); } }); } // Expose immutable LiveData to the UI public LiveData<ArrayList<UserDetails>> getUserListLiveData() { return userListLiveData; } public LiveData<String> getErrorLiveData() { return errorLiveData; } }
Usage in Activity
import androidx.appcompat.app.AppCompatActivity; import androidx.lifecycle.ViewModelProvider; public class YourActivity extends AppCompatActivity { private UserViewModel userViewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_activity_layout); // Initialize ViewModel userViewModel = new ViewModelProvider(this).get(UserViewModel.class); // Observe user list updates userViewModel.getUserListLiveData().observe(this, userList -> { // Update UI with user list }); // Observe errors userViewModel.getErrorLiveData().observe(this, errorMessage -> { // Show error to user }); // Trigger the network request userViewModel.fetchUserList(); } }
Both approaches eliminate duplicate code across Activities. The basic repository pattern works great for simple apps, while the ViewModel approach is ideal for apps that need to handle configuration changes (like screen rotations) gracefully.
内容的提问来源于stack exchange,提问作者Deepak

