Skip to content

Commit 9cd4546

Browse files
Merge pull request #52 from MihaiCristianCondrea/codex/create-data-layer-structure-and-migrate-repositories
Refactor home and quiz repositories into centralized data layer
2 parents 54abd43 + 84f0ac4 commit 9cd4546

16 files changed

+280
-135
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.d4rk.androidtutorials.java.data.repository;
2+
3+
import android.content.Intent;
4+
5+
import com.d4rk.androidtutorials.java.data.source.HomeLocalDataSource;
6+
import com.d4rk.androidtutorials.java.data.source.HomeRemoteDataSource;
7+
import com.d4rk.androidtutorials.java.data.source.HomeRemoteDataSource.PromotedAppsCallback;
8+
9+
/**
10+
* Default implementation of {@link HomeRepository} combining local and remote sources.
11+
*/
12+
public class DefaultHomeRepository implements HomeRepository {
13+
14+
private final HomeRemoteDataSource remoteDataSource;
15+
private final HomeLocalDataSource localDataSource;
16+
17+
public DefaultHomeRepository(HomeRemoteDataSource remoteDataSource,
18+
HomeLocalDataSource localDataSource) {
19+
this.remoteDataSource = remoteDataSource;
20+
this.localDataSource = localDataSource;
21+
}
22+
23+
@Override
24+
public Intent getPlayStoreIntent() {
25+
return localDataSource.getPlayStoreIntent();
26+
}
27+
28+
@Override
29+
public Intent getAppPlayStoreIntent(String packageName) {
30+
return localDataSource.getAppPlayStoreIntent(packageName);
31+
}
32+
33+
@Override
34+
public String getDailyTip() {
35+
return localDataSource.getDailyTip();
36+
}
37+
38+
@Override
39+
public void fetchPromotedApps(PromotedAppsCallback callback) {
40+
remoteDataSource.fetchPromotedApps(callback);
41+
}
42+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.d4rk.androidtutorials.java.data.repository;
2+
3+
import com.d4rk.androidtutorials.java.data.model.QuizQuestion;
4+
import com.d4rk.androidtutorials.java.data.source.QuizLocalDataSource;
5+
6+
import java.util.List;
7+
8+
/**
9+
* Default implementation of {@link QuizRepository} using a local data source.
10+
*/
11+
public class DefaultQuizRepository implements QuizRepository {
12+
13+
private final QuizLocalDataSource localDataSource;
14+
15+
public DefaultQuizRepository(QuizLocalDataSource localDataSource) {
16+
this.localDataSource = localDataSource;
17+
}
18+
19+
@Override
20+
public List<QuizQuestion> loadQuestions() {
21+
return localDataSource.loadQuestions();
22+
}
23+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.d4rk.androidtutorials.java.data.repository;
2+
3+
import android.content.Intent;
4+
5+
import com.d4rk.androidtutorials.java.data.model.PromotedApp;
6+
import com.d4rk.androidtutorials.java.data.source.HomeRemoteDataSource.PromotedAppsCallback;
7+
8+
/**
9+
* Abstraction over home data operations.
10+
*/
11+
public interface HomeRepository {
12+
13+
Intent getPlayStoreIntent();
14+
15+
Intent getAppPlayStoreIntent(String packageName);
16+
17+
String getDailyTip();
18+
19+
void fetchPromotedApps(PromotedAppsCallback callback);
20+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.d4rk.androidtutorials.java.data.repository;
2+
3+
import com.d4rk.androidtutorials.java.data.model.QuizQuestion;
4+
5+
import java.util.List;
6+
7+
/**
8+
* Abstraction over quiz data operations.
9+
*/
10+
public interface QuizRepository {
11+
List<QuizQuestion> loadQuestions();
12+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.d4rk.androidtutorials.java.data.source;
2+
3+
import android.content.Context;
4+
import android.content.Intent;
5+
import android.net.Uri;
6+
7+
import com.d4rk.androidtutorials.java.R;
8+
9+
/**
10+
* Default implementation that reads from Android resources.
11+
*/
12+
public class DefaultHomeLocalDataSource implements HomeLocalDataSource {
13+
14+
private final Context context;
15+
16+
public DefaultHomeLocalDataSource(Context context) {
17+
this.context = context.getApplicationContext();
18+
}
19+
20+
@Override
21+
public Intent getPlayStoreIntent() {
22+
String playStoreUrl = "https://play.google.com/store/apps/details?id=com.d4rk.androidtutorials";
23+
return buildPlayStoreIntent(playStoreUrl);
24+
}
25+
26+
@Override
27+
public Intent getAppPlayStoreIntent(String packageName) {
28+
String url = "https://play.google.com/store/apps/details?id=" + packageName;
29+
return buildPlayStoreIntent(url);
30+
}
31+
32+
@Override
33+
public String getDailyTip() {
34+
String[] tips = context.getResources().getStringArray(R.array.daily_tips);
35+
long daysSinceEpoch = System.currentTimeMillis() / (24L * 60 * 60 * 1000);
36+
int index = (int) (daysSinceEpoch % tips.length);
37+
return tips[index];
38+
}
39+
40+
private Intent buildPlayStoreIntent(String url) {
41+
Intent playStoreIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
42+
playStoreIntent.setPackage("com.android.vending");
43+
if (playStoreIntent.resolveActivity(context.getPackageManager()) != null) {
44+
return playStoreIntent;
45+
}
46+
return new Intent(Intent.ACTION_VIEW, Uri.parse(url));
47+
}
48+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.d4rk.androidtutorials.java.data.source;
2+
3+
import com.android.volley.Request;
4+
import com.android.volley.RequestQueue;
5+
import com.android.volley.toolbox.JsonObjectRequest;
6+
import com.d4rk.androidtutorials.java.data.model.PromotedApp;
7+
8+
import org.json.JSONArray;
9+
import org.json.JSONException;
10+
import org.json.JSONObject;
11+
12+
import java.util.ArrayList;
13+
import java.util.Collections;
14+
import java.util.List;
15+
16+
/**
17+
* Volley based implementation of {@link HomeRemoteDataSource}.
18+
*/
19+
public class DefaultHomeRemoteDataSource implements HomeRemoteDataSource {
20+
21+
private final RequestQueue requestQueue;
22+
private final String apiUrl;
23+
24+
public DefaultHomeRemoteDataSource(RequestQueue requestQueue, String apiUrl) {
25+
this.requestQueue = requestQueue;
26+
this.apiUrl = apiUrl;
27+
}
28+
29+
@Override
30+
public void fetchPromotedApps(PromotedAppsCallback callback) {
31+
JsonObjectRequest request = new JsonObjectRequest(
32+
Request.Method.GET,
33+
apiUrl,
34+
null,
35+
response -> {
36+
List<PromotedApp> result = new ArrayList<>();
37+
try {
38+
JSONArray apps = response.getJSONObject("data").getJSONArray("apps");
39+
for (int i = 0; i < apps.length(); i++) {
40+
JSONObject obj = apps.getJSONObject(i);
41+
String pkg = obj.getString("packageName");
42+
if (pkg.contains("com.d4rk.androidtutorials")) {
43+
continue;
44+
}
45+
result.add(new PromotedApp(
46+
obj.getString("name"),
47+
pkg,
48+
obj.getString("iconLogo")
49+
));
50+
}
51+
} catch (JSONException e) {
52+
result = Collections.emptyList();
53+
}
54+
callback.onResult(result);
55+
},
56+
error -> callback.onResult(Collections.emptyList())
57+
);
58+
requestQueue.add(request);
59+
}
60+
}
Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
package com.d4rk.androidtutorials.java.ui.screens.quiz.repository;
1+
package com.d4rk.androidtutorials.java.data.source;
22

3-
import android.content.Context;
3+
import android.content.res.AssetManager;
44

55
import com.d4rk.androidtutorials.java.data.model.QuizQuestion;
66

@@ -16,25 +16,21 @@
1616
import java.util.List;
1717

1818
/**
19-
* Repository responsible for loading quiz question data from JSON assets.
19+
* Reads quiz questions from the assets folder.
2020
*/
21-
public class QuizRepository {
21+
public class DefaultQuizLocalDataSource implements QuizLocalDataSource {
2222

23-
private final Context context;
23+
private final AssetManager assetManager;
2424

25-
public QuizRepository(Context context) {
26-
this.context = context.getApplicationContext();
25+
public DefaultQuizLocalDataSource(AssetManager assetManager) {
26+
this.assetManager = assetManager;
2727
}
2828

29-
/**
30-
* Loads the quiz questions from the assets folder.
31-
*/
29+
@Override
3230
public List<QuizQuestion> loadQuestions() {
33-
try {
34-
InputStream is = context.getAssets().open("quiz_questions.json");
31+
try (InputStream is = assetManager.open("quiz_questions.json")) {
3532
byte[] buffer = new byte[is.available()];
3633
int read = is.read(buffer);
37-
is.close();
3834
String json = new String(buffer, 0, read, StandardCharsets.UTF_8);
3935
JSONArray array = new JSONArray(json);
4036
List<QuizQuestion> result = new ArrayList<>();
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.d4rk.androidtutorials.java.data.source;
2+
3+
import android.content.Intent;
4+
5+
/**
6+
* Local data access for the home feature.
7+
*/
8+
public interface HomeLocalDataSource {
9+
10+
Intent getPlayStoreIntent();
11+
12+
Intent getAppPlayStoreIntent(String packageName);
13+
14+
String getDailyTip();
15+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.d4rk.androidtutorials.java.data.source;
2+
3+
import com.d4rk.androidtutorials.java.data.model.PromotedApp;
4+
5+
import java.util.List;
6+
7+
/**
8+
* Contract for fetching home screen data from remote sources.
9+
*/
10+
public interface HomeRemoteDataSource {
11+
12+
interface PromotedAppsCallback {
13+
void onResult(List<PromotedApp> apps);
14+
}
15+
16+
void fetchPromotedApps(PromotedAppsCallback callback);
17+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.d4rk.androidtutorials.java.data.source;
2+
3+
import com.d4rk.androidtutorials.java.data.model.QuizQuestion;
4+
5+
import java.util.List;
6+
7+
/**
8+
* Contract for reading quiz data from local storage.
9+
*/
10+
public interface QuizLocalDataSource {
11+
List<QuizQuestion> loadQuestions();
12+
}

0 commit comments

Comments
 (0)