Skip to content

Instantly share code, notes, and snippets.

@sunmeat
Created November 23, 2025 19:27
Show Gist options
  • Select an option

  • Save sunmeat/f964612dfca8ecb05b417eb29bd116e6 to your computer and use it in GitHub Desktop.

Select an option

Save sunmeat/f964612dfca8ecb05b417eb29bd116e6 to your computer and use it in GitHub Desktop.
retrofit android example
build.gradle.kts (Module):
dependencies {
...
implementation("androidx.recyclerview:recyclerview:1.3.2")
implementation("com.squareup.retrofit2:retrofit:3.0.0")
implementation("com.squareup.retrofit2:converter-gson:3.0.0")
implementation("com.google.code.gson:gson:2.11.0")
}
================================================================================================================
MainActivity.java:
package site.sunmeat.helloworld;
import android.os.*;
import android.view.*;
import android.widget.*;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.*;
import com.google.gson.annotations.*;
import java.util.*;
import java.util.concurrent.*;
import retrofit2.*;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.*;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private ProgressBar progressBar;
private JokeAdapter adapter;
private final ArrayList<JokeModel> jokes = new ArrayList<>();
private static final int TOTAL_JOKES = 20;
// === Retrofit 3.0.0 інтерфейс ===
public interface JokeApi {
@GET("joke/Programming")
Call<JokeModel> getJoke(@Query("type") String type); // параметр не обов’язковий, для сумісності
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.posts_recycle_view);
progressBar = findViewById(R.id.progressBar);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new JokeAdapter(jokes);
recyclerView.setAdapter(adapter);
// === Retrofit 3.0.0 ===
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://v2.jokeapi.dev/")
.addConverterFactory(GsonConverterFactory.create())
.build();
JokeApi api = retrofit.create(JokeApi.class);
loadJokes(api);
}
private void loadJokes(JokeApi api) {
ExecutorService executor = Executors.newSingleThreadExecutor();
var mainHandler = new Handler(Looper.getMainLooper());
executor.execute(() -> {
int loaded = 0;
while (loaded < TOTAL_JOKES) {
try {
Call<JokeModel> call = api.getJoke(""); // або просто null
retrofit2.Response<JokeModel> response = call.execute();
if (response.isSuccessful() && response.body() != null) {
JokeModel joke = response.body();
mainHandler.post(() -> {
jokes.add(joke);
adapter.notifyItemInserted(jokes.size() - 1);
recyclerView.scrollToPosition(jokes.size() - 1);
});
loaded++;
} else {
// якщо помилка – трохи почекаємо і спробуємо ще раз
Thread.sleep(500);
}
} catch (Exception e) {
try { Thread.sleep(1000); } catch (InterruptedException ignored) {}
}
}
mainHandler.post(() -> {
progressBar.setVisibility(View.GONE);
if (jokes.isEmpty()) {
Toast.makeText(this, "Не вдалося завантажити жарти", Toast.LENGTH_LONG).show();
}
});
executor.shutdown();
});
}
// ==================== адаптер для списку ====================
private static class JokeAdapter extends RecyclerView.Adapter<JokeAdapter.ViewHolder> {
private final List<JokeModel> jokes;
JokeAdapter(List<JokeModel> jokes) {
this.jokes = jokes;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.post_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
String content = jokes.get(position).getContent();
content = content.replaceAll("! -", "\n-");
holder.textView.setText(content);
}
@Override
public int getItemCount() {
return jokes.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView textView;
ViewHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.post);
}
}
}
// ==================== модель ====================
public static class JokeModel {
@SerializedName("type")
@Expose
private String type;
@SerializedName("joke")
@Expose
private String joke;
@SerializedName("setup")
@Expose
private String setup;
@SerializedName("delivery")
@Expose
private String delivery;
public String getContent() {
if ("single".equals(type) && joke != null) {
return joke;
} else if ("twopart".equals(type) && setup != null && delivery != null) {
return setup + "\n\n" + delivery;
}
return "Жарт не розпарсено";
}
}
}
================================================================================================================
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#121926">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/posts_recycle_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="@android:color/transparent"
android:clipToPadding="false"
android:padding="4dp" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminateTint="#FFFFFF"
android:visibility="visible" />
</RelativeLayout>
================================================================================================================
post_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:orientation="vertical"
android:padding="12dp">
<TextView
android:id="@+id/post"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:fontFamily="sans-serif"
android:lineSpacingExtra="2dp"
android:padding="4dp"
android:textColor="#000000"
android:textSize="16sp"
android:textStyle="normal" />
</LinearLayout>
</androidx.cardview.widget.CardView>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment