システム要件およびツールチェーン
本プロジェクトは、モバイル端末上で実行可能な宿泊施設検索・予約アプリケーションの開発を目的としています。以下の環境構成を採用しました。
- 統合開発環境: Android Studio
- プログラム言語: Java
- JDK レベル: 8 バージョン以降
ユーザーアカウント登録モジュール
新規利用者の情報を取得し、サーバーへ送信する処理を実装します。テキストフィールドからの入力をバリデーションした上で、HTTP リクエストを送信するクラス構成です。
/**
* ユーザー登録画面ロジック
*/
public class AccountCreateActivity extends BaseActivity<ActivityRegisterBinding> {
@Override
protected ActivityRegisterBinding getViewBinding() {
return ActivityRegisterBinding.inflate(getLayoutInflater());
}
@Override
protected void setListeners() {
mBinding.register.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String loginIdentifier = mBinding.username.getText().toString();
String authPassword = mBinding.password.getText().toString();
if (TextUtils.isEmpty(loginIdentifier) || TextUtils.isEmpty(authPassword)) {
showToast("入力必須項目を確認してください");
} else {
OkGo.<String>get(ApiConstants.REGISTRATION_ENDPOINT)
.params("id", loginIdentifier)
.params("pwd", authPassword)
.execute(new HttpStringCallback(AccountCreateActivity.this) {
@Override
protected void onSuccess(String msg, String response) {
showToast(msg);
finish();
}
@Override
protected void onError(String response) {
showToast(response);
}
});
}
}
});
}
@Override
protected void initializeData() {
// 初期状態処理なし
}
}
決済処理ダイアログの実装
注文情報の確認を行い、確定ボタンが押下された際に決済 API を叩く機能を担当しています。外部ライブラリを使用して非同期通信を制御します。
/**
* 支払い確認用のポップアップアクティビティ
*/
public class ConfirmPaymentActivity extends BaseActivity<ActivityPayDialogBinding> {
private TransactionDetail currentTxn;
@Override
protected ActivityPayDialogBinding getViewBinding() {
return ActivityPayDialogBinding.inflate(getLayoutInflater());
}
@Override
protected void attachEventHandlers() {
mBinding.cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
}
});
mBinding.confirmButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (null != currentTxn) {
executePayment(currentTxn.getUserId());
}
}
});
}
private void executePayment(int targetUser) {
OkGo.<String>get(ApiConstants.CHARGE_API)
.params("user_id", targetUser)
.params("status_flag", 1)
.execute(new HttpStringCallback(this) {
@Override
protected void onSuccess(String message, String body) {
showNotification(message);
setResult(1000);
finish();
}
@Override
protected void onError(String responseBody) {
showNotification(responseBody);
}
});
}
@Override
protected void loadInitialData() {
currentTxn = (TransactionDetail) getIntent().getSerializableExtra("booking_data");
if (null != currentTxn) {
mBinding.discountPrice.setText("¥" + currentTxn.getTotalAmount());
}
}
}
ホーム画面リストと検索ロジック
ホテル一覧を取得し、RecyclerView で表示させます。バナー広告の表示や、文字列ベースでの絞り込み処理も含まれます。
public class MainHomeFragment extends BaseFragment<FragmentHomeBinding> {
private HomeListViewAdapter listViewAdapter;
private List<HouseItemDTO> filteredRooms = new ArrayList<>();
@Override
protected FragmentHomeBinding getViewBinding() {
return FragmentHomeBinding.inflate(getLayoutInflater());
}
@Override
protected void setupInteractions() {
listViewAdapter = new HomeListViewAdapter();
mBinding.recyclerView.setAdapter(listViewAdapter);
// リストアイテムのクリックイベント
listViewAdapter.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(@NonNull BaseQuickAdapter, ?> adapter, @NonNull View view, int pos) {
Intent navigationIntent = new Intent(mContext, PropertyDetailActivity.class);
navigationIntent.putExtra("item_data", adapter.getData().get(pos));
startActivity(navigationIntent);
}
});
// 検索バー処理
mBinding.btnSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String query = mBinding.etContent.getText().toString();
if (TextUtils.isEmpty(query)) {
showToast("検索キーワードを入力してください");
} else {
filteredRooms.clear();
List<HouseItemDTO> sourceList = listViewAdapter.getData();
for (int i = 0; i < sourceList.size(); i++) {
HouseItemDTO hotel = sourceList.get(i);
if (hotel.getName().contains(query)) {
filteredRooms.add(hotel);
}
}
listViewAdapter.setList(filteredRooms);
}
}
});
mBinding.etContent.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence c, int s, int n, int a) {}
@Override
public void onTextChanged(CharSequence c, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable e) {
String text = e.toString();
if (TextUtils.isEmpty(text)) {
fetchPropertyList();
}
}
});
}
@Override
protected void initializeComponents() {
// ビルトインバナー設定
mBinding.banner.setAdapter(new BannerImageAdapter<BannerModel>(BannerModel.sampleData()) {
@Override
public void onBindHolder(BannerImageHolder h, BannerModel data, int p, int t) {
h.imageView.setImageResource(data.imageRes);
}
})
.addLifecycleObserver(this)
.setIndicator(new CircleIndicator(getActivity()));
fetchPropertyList();
}
/**
* 宿泊施設リストデータの取得処理
*/
public void fetchPropertyList() {
OkGo.<String>get(ApiConstants.INVENTORY_URL)
.execute(new HttpStringCallback(getActivity()) {
@Override
protected void onSuccess(String statusMsg, String jsonPayload) {
InventoryResponse responseData = GsonUtils.parseJson(jsonPayload, InventoryResponse.class);
listViewAdapter.setList(responseData.getItemList());
}
@Override
protected void onError(String errorMsg) {
showToast(errorMsg);
}
});
}
}