首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Android Fragment 實戰:下拉刷新、上拉加載更多與 RecyclerView/ListView 綁定完整範例

     編輯:Java 程式設計入門

業務場景

新聞/資訊類 App 典型需求:Fragment 承載列表,支持下拉刷新重置數據、上拉分頁加載追加數據、點擊跳轉詳情。

核心組件

  • PullToRefreshLayout:自定義佈局,封裝下拉/上拉手勢識別與動畫。
  • PullableListView:實現 Pullable 介面的 ListView,配合刷新佈局判斷是否到達頂/底部。
  • Handler:主線程更新 UI,處理網絡回調消息。
  • Gson:JSON 解析為實體類。
  • NewShuju (Adapter):列表適配器,支持 UpDataAdapter 刷新/追加模式。

Fragment 完整代碼 (關鍵邏輯註釋)


public class NewsFragment extends Fragment {
    // UI 組件
    private PullToRefreshLayout refreshLayout;
    private PullableListView listView;
    private TextView categoryTv;
    
    // 數據
    private List dataList = new ArrayList<>();      // 當前頁數據
    private List allData = new ArrayList<>();       // 累計數據 (上拉追加用)
    private NewsAdapter adapter;
    
    // 分頁
    private int page = 0;
    private String categoryUrl; // 從 Bundle 獲取
    
    // Handler 處理網絡回調
    private Handler handler = new Handler(msg -> {
        String json = (String) msg.obj;
        List pageData = new Gson().fromJson(json, new TypeToken>(){}.getType());
        
        if (msg.what == REFRESH) { // 下拉刷新
            dataList.clear();
            dataList.addAll(pageData);
            allData.clear();
            allData.addAll(pageData);
            page = 1;
        } else if (msg.what == LOAD_MORE) { // 上拉加載
            dataList.clear(); // 適配器只顯示最新頁?或 allData.addAll(pageData) 視需求
            allData.addAll(pageData);
            page++;
        }
        adapter.notifyDataSetChanged(); // 或 adapter.upDataAdapter(allData)
        refreshLayout.refreshFinish(PullToRefreshLayout.SUCCEED);
        refreshLayout.loadmoreFinish(PullToRefreshLayout.SUCCEED);
        return true;
    });

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_news, container, false);
        // 初始化視圖
        refreshLayout = view.findViewById(R.id.refreshLayout);
        listView = view.findViewById(R.id.listView);
        categoryTv = view.findViewById(R.id.categoryTv);
        
        // 設置日期
        setCurrentDate();
        
        // 獲取傳入參數 (category)
        Bundle args = getArguments();
        if (args != null) categoryUrl = UrlMap.getUrl(args.getString("category"));
        
        // 適配器
        adapter = new NewsAdapter(getActivity(), allData, listView);
        listView.setAdapter(adapter);
        
        // 點擊跳轉詳情
        listView.setOnItemClickListener((parent, v, pos, id) -> {
            NewsItem item = allData.get(pos);
            Intent intent = new Intent(getActivity(), DetailActivity.class);
            intent.putExtra("url", item.getUrl());
            intent.putExtra("img", item.getImageUrl());
            intent.putExtra("title", item.getTitle());
            startActivity(intent);
        });
        
        // 刷新/加載監聽
        refreshLayout.setOnRefreshListener(new OnRefreshListener() {
            @Override public void onRefresh(PullToRefreshLayout layout) {
                page = 0;
                loadData(categoryUrl, REFRESH);
            }
            @Override public void onLoadMore(PullToRefreshLayout layout) {
                loadData(categoryUrl, LOAD_MORE);
            }
        });
        
        // 首次加載
        loadData(categoryUrl, REFRESH);
        return view;
    }
    
    private void loadData(String url, int type) {
        new Thread(() -> {
            String json = NetUtil.get(url + (type == LOAD_MORE ? page : ""));
            handler.sendMessage(handler.obtainMessage(type, json));
        }).start();
    }
    
    private void setCurrentDate() { /* Calendar 格式化設置 TextView */ }
}

關鍵技術點解析

  1. 分頁邏輯:刷新重置 page=0、清空列表;加載遞增 page++、追加數據。URL 拼接頁碼參數。
  2. 數據源管理:維護兩個列表——dataList (適配器當前顯示) 與 allData (全量累計)。根據產品需求決定適配器綁定哪個 (瀑布流通常綁 allData)。
  3. Handler 防內存洩漏:靜態內部類 + WeakReference<Fragment>,或 Fragment.onDestroy() 移除消息 handler.removeCallbacksAndMessages(null)。
  4. 網絡請求:子線程 NetUtil.get(),完成後 handler.sendMessage() 切回主線程解析更新 UI。
  5. 列表復用優化:Adapter.getView() 使用 ViewHolder 模式,convertView 復用。
  6. Fragment 生命週期:onCreateView 返回 view 前判斷 view.getParent() != null 移除,防止重複添加報錯。

現代替代方案 (推薦)

舊方案現代替代優勢
ListView + 自定義刷新佈局RecyclerView + SwipeRefreshLayout / SmartRefreshLayout項目解耦、動畫豐富、支持 Grid/Staggered、性能更好
Handler + ThreadRxJava / Coroutines (Flow) / Retrofit + LiveData鏈式調用、生命週期感知、取消簡單、異常處理統一
Gson 手動解析Moshi / Kotlinx SerializationKotlin 友好、性能更強、類型安全
Fragment 手動管理Jetpack Navigation + ViewBinding導航圖可視化、安全參數傳遞、返回棧自動管理

總結

這個 Fragment 範例展示了 Android 傳統開發模式下「列表刷新分頁」的完整閉環:視圖綁定、手勢識別、異步網絡、JSON 解析、主線程更新、分頁狀態管理。理解這套邏輯,有助於維護老項目、遷移到現代架構時做對應映射。**新項目請直接上 RecyclerView + Jetpack 全家桶。**

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved