flutter實戰(zhàn)3:解析HTTP請求數(shù)據(jù)和制作新聞分類列表

當我們搭建好了整個APP的頁面框架,現(xiàn)在我往Tab頁里加點東西:各種分類的新聞列表。也可以參考我的Git,上面有要點注釋。

本次的任務目的

由于需要請求外部數(shù)據(jù),因此引入一個較為方便的http庫。官方示例的httpClient也是可以的,但是坑略多,待會兒講。

第一步

調(diào)整代碼結構,定義一個Tab頁內(nèi)通用的列表對象,這種場景下使用ListView.builder()創(chuàng)建不定長度的列表:

//因為列表的長度不定,因此需要用有狀態(tài)類來承載列表
class NewsList extends StatefulWidget{
  final String newsType;    //新聞類型
  @override
  NewsList({Key key, this.newsType} ):super(key:key);

  _NewsListState createState() => new _NewsListState();
}

class _NewsListState extends State<NewsList>{
  ...
  @override
  Widget build(BuildContext context){
    return new ListView.builder(        //ListView.builder非常適合用于創(chuàng)建不確定長度的的列表
        padding: const EdgeInsets.all(16.0),
        itemCount: data == null ? 0 : data.length,
        itemBuilder: (context, i) {
          return _newsRow(data[i]);//把數(shù)據(jù)項塞入ListView中
        }
      );
  }
  ...
}

Tab頁的數(shù)據(jù)表達進行結構化處理,在最外層定義新聞Tab頁的類,方便后面使用:

//定義TAB頁對象,這樣做的好處就是,可以靈活定義每個tab頁用到的對象,可結合Iterable對象使用,以后講
class NewsTab {
  String text;
  NewsList newsList;
  NewsTab(this.text,this.newsList);
}

_MyTabbedPageState對象中實例化這些Tab:

//將每個Tab頁都結構化處理下,由于http的請求需要傳入新聞類型的參數(shù)newsType,因此將新聞類型參數(shù)值作為對象屬性傳入Tab中
  final List<NewsTab> myTabs = <NewsTab>[
    new NewsTab('頭條',new NewsList(newsType: 'toutiao')),    //拼音就是參數(shù)值
    new NewsTab('社會',new NewsList(newsType: 'shehui')),
    new NewsTab('國內(nèi)',new NewsList(newsType: 'guonei')),
    new NewsTab('國際',new NewsList(newsType: 'guoji')),
    new NewsTab('娛樂',new NewsList(newsType: 'yule')),
    new NewsTab('體育',new NewsList(newsType: 'tiyu')),
    new NewsTab('軍事',new NewsList(newsType: 'junshi')),
    new NewsTab('科技',new NewsList(newsType: 'keji')),
    new NewsTab('財經(jīng)',new NewsList(newsType: 'caijing')),
    new NewsTab('時尚',new NewsList(newsType: 'shishang')),
  ];

第二步

由于重新了Tabs,原來的TabBar和TabBarView獲取對應值的方式也發(fā)生了改變,用map+toList方法處理下:

@override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        backgroundColor: Colors.orangeAccent,
        title: new TabBar(
          controller: _tabController,
          tabs: myTabs.map((NewsTab item){      //NewsTab可以不用聲明
            return new Tab(text: item.text==null?'錯誤':item.text);
          }).toList(),    //記住要用toList()轉換一下map的結果,否則會由于類型不匹配而報錯
          indicatorColor: Colors.white,
          isScrollable: true,   //水平滾動的開關,開啟后Tab標簽可自適應寬度并可橫向拉動,并自動從左到右排列,默認關閉
        ),
      ),
      body: new TabBarView(
        controller: _tabController,
        children: myTabs.map((item) {
          return item.newsList; //使用參數(shù)值
        }).toList(),
      ),
    );
  }

以上對新聞頁面的結構進行了重構,重頭戲就是完善NewsList對象。于是乎,在初始化NewsList對象時發(fā)起HTTP請求應該是個不錯的辦法:

initState方法中數(shù)據(jù)初始化

具體是怎么初始化數(shù)據(jù)的,第三步會講到,踩了不少坑。這里的重點是,F(xiàn)lutter提倡數(shù)據(jù)驅動組件的創(chuàng)建,組件自己無法觸發(fā)動態(tài)創(chuàng)建對象,只有通過數(shù)據(jù)綁定的方式,實現(xiàn)對象的重繪和動態(tài)加載,原理和react類似,比如:

數(shù)據(jù)驅動組件重繪

第三步

到了這一步,完全進入踩坑模式。

  • 踩坑1 http和httpclient都是IO異步操作,其內(nèi)置的請求函數(shù)的返回值是Future類型對象,需要提前聲明定義類型如:Future<String>,返回值也需要await異步處理后才可以轉換成需要的數(shù)據(jù)類型:
Future的數(shù)據(jù)類型注意事項

上圖中列舉了兩種方法,建議使用下面那種,因為如果能從返回值中提取請求獲取的數(shù)據(jù),即可將所有的http請求封裝到API文件中去,不必寫在頁面代碼中,原因大家都懂的。
注意在setState()之前有一句if(!mounted) return,因為異步請求數(shù)據(jù)和控件的渲染是同時進行的,如果代碼已經(jīng)執(zhí)行到了setState,但是數(shù)據(jù)還沒有獲取到,此時setState觸發(fā)的控件渲染就會報錯,為了避免這種空值錯誤,在setState之前先判斷空間是否已經(jīng)渲染完成,mountedFlutter內(nèi)置的當前控件的狀態(tài)標識,記住就好。

  • 踩坑2 在ListView直屬的Column里面不能用Expanded控件
    Column里面不能用Expanded控件

圖中的提示說使用Flexible控件更佳,然而實際上Flexible也會報錯。報錯的英文大概意思是ListView控件生成未知長度的列表時,總是會自動壓縮每一個子元素的高度,而ExpandedFlexible都是可以自由伸縮的控件,造成ListView的子元素無法確定繪制的高度,為了使超出屏幕寬度的新聞標題自動換行,這個時候用ListTile頂替一下吧。

  • 踩坑3 處理不同新聞圖片數(shù)量不一致的問題
想象中的樣子

如上圖,肯定是不行的,控件的子元素是不允許為空的,于是使用條件判斷的方式封裝一下:

根據(jù)圖片數(shù)量的不同插入合適尺寸樣式的圖片
  • 踩坑3 深刻體會map數(shù)組和Object數(shù)組的使用,newsinfo.["title"]newsinfo.title兩者的newsinfo類型是不一樣的,詳細還是到源碼中去體會吧,注意對比newsinfomyTab這兩個的用法。

這次頁面寫的非常辛苦,而且還沒實現(xiàn)滾動刷新或頂部下拉刷新的效果,下一篇再更吧,還有很多要點我在源碼中有標識,可以去我的Git中慢慢品味,今天就更到這里,滾去睡覺,真的來不起了。

感謝大家的支持,請關注我的Flutter圈子,多多投稿,也可以加入flutter 中文社區(qū)(官方QQ群:338252156)共同成長,謝謝大家~

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,323評論 25 708
  • 佛說:人生有八苦:生,老,病,死,愛別離,怨長久,求不得,放不下。時間就像一場回不去的旅行;爭不過朝夕,又...
    歲月神偷123閱讀 563評論 0 0
  • 端午節(jié)作為四大傳統(tǒng)節(jié)日之一,節(jié)日的氣氛自當異常濃烈。關于端午,好像有永遠討論不完的話題,今天總結一下關于端午那些事...
    Joyful_Cheung閱讀 335評論 4 2
  • 近期看了一些文章講制定計劃的重要性及制定方法,這使我想到了一句諺語“一年之計在于春,一天之計在于晨”。 計劃容易,...
    霹靂小青龍閱讀 1,792評論 0 1

友情鏈接更多精彩內(nèi)容