(安卓,flutter)【项目记录】flutter项目记录,各种大坑小坑

博客文章链接:https://hanbaoaaa.xyz/index.php/archives/23/k.html
已经完成了。在这里总结一下。

图片名称 一开始刚接触flutter先搞了下界面布局

然后是做和服务器的接口访问。

使用的是dio的库。为了使用方便 再次封装了一下。

import 'package:dio/dio.dart';
import 'main.dart';

class HttpUtil{
  static String tokenHttp;
  bool getting=false;
  static Options options= Options(headers: {"token": tokenHttp});
  static updateHttpUtil(){
    options=Options(headers: {"token": tokenHttp});
    //print("update:"+options.headers.toString());
  }
  onlyParaHttp(var data,String address,{String absoluteAddress})async{
    //print(options.headers);
    try {
      Response response;
      if(data==null){
        response = await Dio().post(
          absoluteAddress==null?RootAddress + address:absoluteAddress,
          options: options,
        );
      }else{
        response = await Dio().post(
          absoluteAddress==null?RootAddress + address:absoluteAddress,
          options: options,
          queryParameters: data,
        );
      }

      return response.data;
    } catch (e) {
      //Toast.toast(context1, msg: "链接超时", position: ToastPostion.bottom);
      getting = false;
      print("httpfailed:"+absoluteAddress==null?RootAddress + address:absoluteAddress);
      return print(e);
    }
  }
  onlyPara(var data,String address,Null whenComp(val),{String absoluteAddress}){

    if(!getting){
      getting=true;
      onlyParaHttp(data,address,absoluteAddress: absoluteAddress).then((val){
        getting=false;
        return val;
      }).then(whenComp);
      return false;
    }else{
      return true;
    }
  }

}

将token设置为静态变量。这里提一下。建议把面向对象里的全局变量设置成静态变量。之前普通的全局变量是相当于一直加载着的,会面临不更新的情况,dart里面的非必要参数写在{ }里面和js比较像。

然后的话dart里的函数可以像参数一样传递。不用像java c#那种要借助委托来实现。所以把回调函数作为参数传递给整个执行函数就行了。然后再http接受完的.then();里面执行回调的函数


然后是弹出窗口。

showDialog<Null>(
    context: context,
    barrierDismissible: false,
    builder: (BuildContext context) {
        return StatefulBuilder(
            builder: (context, state) {
                return new AlertDialog(
                    title: new Text('当前剧本要花费'+fee.toString()+"个币"),
                    actions: <Widget>[
                        new FlatButton(
                            child: new Text('取消'),
                            onPressed: () {
                                Navigator.of(context).pop();
                            },
                        ),
                        new FlatButton(
                            child: new Text(text),
                            onPressed: (){
                                buyHttp.onlyPara({
                                    "id":id
                                }, "/buyFileServlet", (val){
                                    ////print(val);
                                    switch(val['status']){
                                        case 454:
                                            state(() {
                                                text="余额不足";
                                            });
                                            break;
                                        case 1:
                                            Navigator.of(context).pop();
                                            gotoDetail(index,pagecount);
                                            break;
                                    }
                                });
                            },
                        ),
                    ],
                );

            },
        );

    },
);

使用statefulBuilder可以动态的更新弹出窗口内的内容。不过setstate名字被参数名替换掉了。


Navigator.of(context)..pop()..pop("deleted!");

使用这个语句来连续弹出两个页面,


waitForUpload(BuildContext context) async {
  var result=await Navigator.of(context1).pushNamed('/jubenUpload', arguments: {"name": "上传我的剧本"});
  print('result');
  print(result);
  if(result!=null){
    updateInfo();
  }

}

使用这种异步函数来抓取弹出后返回的变量。


flutter的build函数属于一直在执行的那种。

@override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

这个函数的话属于初始话只执行一次。

像界面启动后做请求或者做弹窗就可以用这个。

但是一定要在build完毕的时候执行界面绘制。

所以界面绘制相关的内容。要用来注册回调。这个回调只会被执行一次。

WidgetsBinding.instance.addPostFrameCallback((_){
    /// 接口请求if (
    getList.onlyPara({
      "type":0
    }, "/showUserFileServlet", (val){
      ////print(val['list']);
      jubenstate.setState((){
        ////print(list);
        list=val['list'];
      });
      authors=List(list.length);
      for(int i=0;i<val['list'].length;i++){
        HttpUtil getname= HttpUtil();
        getname.onlyPara({"userid":list[i]['user_id']}, "/usernameServlet", (val1){
          ////print(val1);

          authors[i]=(val1['username']);
          jubenstate.setState((){});
        });
      }
      ////print(authors.length);
      ////print(list.length);

    });
  });

这里面我state是作为全局变量共享的。实际不建议这样。以后一定要作为参数传递。或者干脆把setstate这句话作为函数传递。


在flutter里函数是变量。可以写成局部函数。也可以作为参数传递。


文件管理。直接嫖的网上现成,但不知道怎么调用系统文件管理。


关于网络权限

,安卓新的api需要申请各种权限。

这几个权限是比较基本的,加载java的AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

还有网络访问http需要做手脚。不然会在视频播放里连不上。

这里要对flutter的AndroidManifest.xml做处理。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.juben">
    <!-- io.flutter.app.FlutterApplication is an android.app.Application that
         calls FlutterMain.startInitialization(this); in its onCreate method.
         In most cases you can leave this as-is, but you if you want to provide
         additional functionality it is fine to subclass or reimplement
         FlutterApplication and put your custom class here. -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="juben"
        android:networkSecurityConfig="@xml/network_security_config"
        android:usesCleartextTraffic="true"
        android:icon="@mipmap/ic_launcher">


        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"

            android:windowSoftInputMode="adjustResize">

            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>

android:networkSecurityConfig="@xml/network_security_config"重点是这一句

在res文件夹里建xml文件夹。xml文件夹里建xml文件。内容为:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">106.15.206.164</domain>
    </domain-config>
</network-security-config>

ip位置写允许http的ip或者域名。


好了。要说的说完了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章