当前位置: 代码迷 >> Android >> 在React-Native中处理服务调用的通用基类方法
  详细解决方案

在React-Native中处理服务调用的通用基类方法

热度:52   发布时间:2023-08-04 10:19:47.0

目标:
一个泛型方法,它通过我的Network类显示一个微调器来调用Web服务,同时完成后将其删除,然后通过显示警报最终处理错误(如果有),否则将响应发送回我的调用类。

我做了什么:我已经在基础类中编写了以下方法,并且所有类都将具有此方法。

问题:调用setState来更新屏幕,因此出现任何警报(错误/成功)片刻,然后最后一个屏幕出现在前面,并且由于警报在屏幕后面而卡住了所有东西。

要求 :任何人都可以指出我在做什么错误或如何解决此问题的任何概念。

import React, { Component } from 'react'
import { View } from 'react-native'
import Network from './Network';

export default class BaseClass extends Component {
   constructor() {
      super()
      this.state = {
         spinner:false,
         response:''
      }
   }

  onPress(data){
      this.setState({ spinner: true })

      var net = new Network();
      net.makeCall(data,function(context,err,res){
      context.setState({ spinner: false })

      if(err!= null){
       alert('error')
      }
      else{
         alert('sccess')
      }
      )
     }
}

第二个方法我都采用第二种方法,但这里得到相同的结果。

import React, { Component } from 'react'
    import { View } from 'react-native'
    import Network from './Network';

    export default class BaseClass extends Component {
       constructor() {
          super()
          this.state = {
             spinner:false,
             response:''
          }
       }

      onPress(data){
          this.setState({ spinner: true })

          var net = new Network();
          net.makeCall(data,function(context,err,res){
          context.setState({ spinner: false })

          if(err!= null){
           context.setState({ response: err })
          }
          else{
             context.setState({ response: data })
          }
          )
       }

    componentDidUpdate(){
    alert(this.state.response)
    }
    }

我当前的工作类,很少有一些类是自定义类,例如Screens,SessionManager,SessionTimer,Constants

"use strict";
import React, {Component} from 'react';
import Spinner from 'react-native-loading-spinner-overlay';
import Pinch from 'react-native-pinch';
import Config from './Config'
import {SessionManager} from './utilities/SessionManager';
import Constants from './utilities/Constants'
import {Platform, Alert} from 'react-native';
import {Screens} from './navigation/Screens'
import SessionTimer from './utilities/SessionTimer';
import IMEI from './utilities/IMEI'
// Check Device Info
var DeviceInfo = require('react-native-device-info');

//import Spinner from  'react-native-spinkit'

/*
 this class will be used to communicate with
 server and getting url params from the calling class,
 handles the server error if there is no error it will
 return the repsonse to the calling class
 */
export class WebServiceCallManager extends Component {

    constructor(props) {
        super(props);
        this.state = {
            visible: this.props.visible,
            size: 100,
        }
    }

    callWebService(requestAction, subAction, bodyParams, responseHandler, optionalErrHandler) {
        this.setState({visible: true});//Starting the Processing indicator
        let imei = null;
        if (Platform.OS === 'android') {
            imei = SessionManager.getSessionValue("IMEI");
        }

        var params = {
            "Header": {
                "AppVersion": DeviceInfo.getVersion(),
                //"IMEI":imei,
                //"DEVICE_MAKE" : (Platform.OS === 'android') ?  "AN": (Platform.OS === 'ios') ? "IP" : "OT",
                "Channel": (Platform.OS === 'android') ? 'MOBILE_ANDROID' : (Platform.OS === 'ios') ? "MOBILE_IOS" : null,
                // DeviceInfo.getManufacturer()
                //    "Channel":DeviceInfo.getManufacturer(),
                //"DeviceId": DeviceInfo.getUniqueID(),
                //  "NetworkType": "MOBILE DATA 3G",
                "RequestAction": requestAction,
                "SubAction": subAction,
                "Token": SessionManager.getSessionValue(Constants.TOKEN),
                //  "Operator": "ZONG",
                "CSRF": SessionManager.getSessionValue(Constants.CSRF),
                //"OS": DeviceInfo.getSystemVersion(),
                "DeviceInformation": {
                    "IMEI": imei,
                    "Manufacturer": DeviceInfo.getManufacturer(),
                    "Model": DeviceInfo.getModel(),
                    "DeviceId": DeviceInfo.getUniqueID(),
                    "DeviceMake": (Platform.OS === 'android') ? "AN" : (Platform.OS === 'ios') ? "IP" : "OT",
                    "OS": DeviceInfo.getSystemVersion(),
                }

            },
            "Body": {
                "Transaction": bodyParams
            }
        };

        var url = Config.IP;

        if (url.startsWith('https')) {
            this._httpsCalling(url, params, responseHandler, optionalErrHandler);
        } else {
            this._httpCalling(url, params, responseHandler, optionalErrHandler);
        }
    }

    _httpsCalling(url, params, responseHandler) {
        Pinch.fetch(url,
            {
                method: "POST",
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(params),
                sslPinning: {
                    cert: 'prodcer'
                }
            })
            .then((responseResult) => {
                this.setState({visible: false});// removing the Processing symbol
                var result = JSON.parse(responseResult.bodyString);
                var strResult = JSON.stringify(result);
                if (responseResult.status == '0') {
                    responseHandler(strResult);
                }
                else {
                    responseHandler(strResult);

                }
            }).catch((err) => {
            this.setState({visible: false});// removing the Processing symbol
            responseHandler(err.message + '');
        })
            .done();
    }

    _httpCalling(url, params, responseHandler, optionalErrHandler) {
        fetch(url,
            {
                method: "POST",
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(params)

            })
            .then((resType) => resType.json())
            .then((responseResult) => {
                let timer = new SessionTimer();
                timer.resetSessionTimer(0);
                this.setState({visible: false});// removing the Processing symbol
                SessionManager.setSessionValue(Constants.TOKEN, responseResult.Header.Cookie);
                SessionManager.setSessionValue(Constants.CSRF, responseResult.Header.CSRF);
                if (responseResult.Header.ResponseCode == '0') {

                    responseHandler(responseResult);
                }
                else {
                    if (optionalErrHandler !== undefined) {
                        optionalErrHandler(responseResult.Header);
                    }
                    this.errorHandler(responseResult.Header);
                    // responseHandler(null ,responseResult.Header.ResponseMessage);

                }
            }).catch((err) => {

            var error = {ResponseMessage: err.message};

            if (optionalErrHandler !== undefined) {
                optionalErrHandler(error);
            }

            this.errorHandler(error);
        })
            .done();
    }

    errorHandler(errorData) {

        this.setState({visible: false});// removing the Processing symbol

        let msg = errorData.ResponseMessage;
        let errorCode = errorData.ResponseCode;

        if (errorCode == 111) {
            setTimeout(
                () => {
                    Alert.alert('Respose Error ' +
                        msg,
                        '',
                        [
                            {
                                text: 'OK', onPress: () => {
                                this.props.nav.popToRoute(Screens.LoginScreen)
                            }
                            },
                        ],
                        {cancelable: false}
                    )
                },
                100
            );
        }
        else {

            setTimeout(
                () => {
                    alert(msg)
                },
                100
            );
        }
    }

    render() {
        return <Spinner visible={this.state.visible} itemProp='size:100'/>
    }
}

编辑2019年9月16日:

在这里,我添加了另一个类,该类使用了我上面定义的网络类,实际上是React世界中的一个组件,因此在render方法内部,我们添加了该组件并获得了对该组件的引用,并在该引用上调用方法callWebService()

import React, { Component } from 'react';

import {  StyleSheet, Text, View, Button,Switch, Alert, Image, TouchableHighlight, Dimensions, Platform,AppState } from 'react-native';
import Constants from '.././utilities/Constants'
import {Screens} from '.././navigation/Screens'
import {ScreenClass} from '.././navigation/Screens';
import TextInputCustom from '.././components/TextInputCustom';
import {SessionManager} from '../utilities/SessionManager';
import {WebServiceCallManager} from '.././WebServiceCallManager';
import {NavigationManager} from '.././navigation/NavigationManager';
import Fingerprint from '.././fingerprint/FingerprintAndroid';


const dismissKeyboard = require('dismissKeyboard');
const { width, height } = Dimensions.get("window");
let opacity = 1;
// source address of login background image
const loginBackgroundViewImg = require('.././assets/login_box.png');
const biometricImage = require('.././assets/biometric_icon.png');

var langs = new Constants(); // language localization


/* Login View for displaying TextInputs(username, passwords),
   Buttons (Login, Register) and Labels (Terms & condition , forget password)
*/

export class LoginContainer extends Component {
     constructor(props){
          super(props);
          this.state = {
            username: '' , // user33
            password: '', // Awaqas@2
            emptyInputFields : '',
            falseSwitchIsOn : true,
            phase: 'normal',
            message: '',
            cancelled: false
          }
     }



     componentDidMount() {
      //  Fingerprint.saveCredentials("user33","Awaqas@2",()=>{
      //   this.setState({
      //       phase: 'saved',
      //       message: ''
      //   });
      //  },()=>{});

            this.authenticate();

             AppState.addEventListener("change", async(state) => {
                 try {
                     if(state === "active" && await Fingerprint.isAuthenticationCanceled()) {
                         this.authenticate()
                     }
                 }
                 catch(z) {
                     console.error(z)
                 }
             })
         }

         async componentWillUnmount() {
             try {
                 if(!Fingerprint.isAuthenticationCanceled()) {
                     //stop listening to authentication.
                     await Fingerprint.cancelAuthentication();
                 }
             } catch(z) {
                 console.error(z);
             }
         }

         async authenticate() {

             try {
                 // do sanity checks before starting authentication flow.
                 // HIGHLY recommended in real life usage. see more on why you should do this in the readme.md
                 const hardware = await Fingerprint.isHardwareDetected();
                 const permission = await Fingerprint.hasPermission();
                 const enrolled = await Fingerprint.hasEnrolledFingerprints();

                 if (!hardware || !permission || !enrolled) {
                     let message = !enrolled ? 'No fingerprints registered.' : !hardware ? 'This device doesn\'t support fingerprint scanning.' : 'App has no permission.'
                     this.setState({
                         phase: 'fail',
                         message
                     });
                     return;
                 }

                  await Fingerprint.authenticate(warning => {
                     this.setState({
                         phase: 'warn',
                         message: warning.message
                     })
                 });

                 // if we got this far, it means the authentication succeeded.
                 this.setState({
                     phase: 'success',
                     message: ''
                 });

                 // in real life, we'd probably do something here (process the payment, unlock the vault, whatever)
                 // but this is a demo. so restart authentication.
                // setTimeout(() => this.authenticate(), 3000);

             } catch (error) {
                 if(error.code == Fingerprint.FINGERPRINT_ERROR_CANCELED) {
                     // we don't show this error to the user.
                     // we will check if the auth was cancelled & restart the flow when the appstate becomes active again.
                     return;
                 }
                 this.setState({
                     phase: 'fail',
                     message: error.message
                 })
             }
         }

      buttonsHandler(type){
          switch (type) {
               case 'forgotpassword':
                    this.props.navigation.push(Screens.ForgotPasswordScreen);
                    break;
               case 'forgotuserid':
                this.props.navigation.push(Screens.ForgotUserIDScreen);
                    break;
               case 'unlockprofile':
                this.props.navigation.push(Screens.UnlockProfileScreen);
                    break;
              case 'register':
                  dismissKeyboard();
                  this.props.navigation.push(Screens.RegistrationWelcomeScreen);
                  break;
               case 'login':
                    this.loginWebServiceCall();
                    break;
               default:
                     alert(type + ' is pressed');

          }
    }


    // this will be called when user hit login button

    loginWebServiceCall()
    {

         if(this.state.username.length === 0 &&  this.state.password.length === 0){
            this.setState({emptyInputFields:langs.strings.login_userid_password_empty});
            this.userName.textFocus();
         }
         else if (this.state.username.length === 0 ) {
           this.setState({emptyInputFields:langs.strings.login_userid_empty});
           this.userName.textFocus();
         }
         else if ( this.state.password.length === 0) {
           this.setState({emptyInputFields:langs.strings.login_password_empty});
           this.password.textFocus();

         }else{
              this.setState({emptyInputFields:''});
              var params = {
                   "Password": this.state.password,
                   "UserName": this.state.username,
                   "LoginType": 'Manual',
              };

              this.webservicemanager.callWebService("LOGIN","TRANSACTION",params,(response) => {this.handleWebServiceCallResponse(response);});
         }
    }

    /* handle the web service successfull response error
    response will be handled inside WebServiceCallManager */

    handleWebServiceCallResponse(data){

        dismissKeyboard();

        var userData = {
            "username":this.state.username,
            "password":this.state.password
        }
        var passwordPolicy = {
          "passwordPolicy" : data.Body.Transaction.PasswordPolicy,
          "passwordPolicyRegex" : data.Body.Transaction.PasswordPolicyRegex
        }

        SessionManager.setSessionValue(Constants.FASTTRANSFER_BENEFICIARY_BRANCH_LIST,data.Body.Transaction.BranchList);
        SessionManager.setSessionValue(Constants.BENEFICIARY_COUNTRY,data.Body.Transaction.CountryList);
        SessionManager.setSessionValue(Constants.BENEFICIARY_RELATIONSHIP, data.Body.Transaction.RelationList);
        SessionManager.setSessionValue(Constants.LOGIN_USERDATA, userData);
        SessionManager.setSessionValue(Constants.CUSTOMER_NUMBER,data.Body.Transaction.CUSTNO);
        SessionManager.setSessionValue(Constants.PASSWORD_POLICY, passwordPolicy);
        SessionManager.setSessionValue(Constants.SECURITY_QUESTIONS_LIST,data.Body.Transaction.Questions);
        var nextScreenName = data.Body.Transaction.NextScreenName;

        const SpecificScreenClass = ScreenClass.getClassFromClassName(nextScreenName);
        SessionManager.setSessionValue('nextScreenName', nextScreenName);
        this.props.navigation.push(SpecificScreenClass);


        this.setState({
             username:'',
             password:'',
             emptyInputFields:''
        });
        this.userName.textClear();
        this.password.textClear();
        dismissKeyboard();

    }

    // handling text input field focus
   textHandler(){
     this.password.focus();
   }

   onSwitchToggle(value){
     if(value){
        opacity = 1;
      }
     else{
       opacity= 0.4;
     }
     this.setState({falseSwitchIsOn: value});
   }

     render(){
       this.fetchCredentials(this.webservicemanager,this.handleWebServiceCallResponse.bind(this));

          return(
               <View style={ styles.loginView}>
                 <Image style={ styles.loginViewBackground} source={loginBackgroundViewImg}>


                 <View>

                   <TextInputCustom
                        ref ={(ref) => this.userName = ref}
                        placeholder={langs.strings.login_userid_placeholder}
                        secureTextEntry={false}
                        onChangeTextCallback={val => this.setState({'username' : val})}
                        returnKeyType="next"
                        textInputWidth = {((width*86)/100)}
                        // onEndEditingCallback = {() => this.password.textFocus()}
                   />

                   <TextInputCustom
                        ref ={(ref) => this.password =ref}
                        placeholder={langs.strings.login_password_placeholder}
                        secureTextEntry={true}
                        onChangeTextCallback={val => this.setState({'password' : val})}
                        returnKeyType="done"
                        textInputWidth = {((width*86)/100)}
                   />
                   <Text style={ styles.emptyInputFields}>{this.state.emptyInputFields}</Text>
                 </View>
                 <View style={ styles.middleContainerViewButtons}>
                   <View style={ styles.middleContainerViewButtonsBtn}>
                     <TouchableHighlight onPress={ () => this.buttonsHandler('login')}>
                       <Text style={ styles.btnTextLabels}>{langs.strings.login_btnLogin}</Text>
                     </TouchableHighlight>
                   </View>
                   <View style={ styles.middleContainerViewButtonsBtn}>
                     <TouchableHighlight onPress={() => this.buttonsHandler('register')}>
                       <Text style={ styles.btnTextLabels}>{langs.strings.login_btnRegister}</Text>
                     </TouchableHighlight>
                   </View>
                 </View>
                 <TouchableHighlight onPress={() => {this.buttonsHandler('forgotpassword')}} underlayColor = {'transparent'}>
                   <Text style={ styles.labels} >
                     Forogot Password
                   </Text>
                 </TouchableHighlight>
                 <TouchableHighlight onPress={() => {this.buttonsHandler('forgotuserid')}} underlayColor = {'transparent'}>
                   <Text style={ styles.labels} >
                     Forogot User ID
                   </Text>
                 </TouchableHighlight>
                 <TouchableHighlight onPress={() => this.buttonsHandler('terms')} underlayColor = {'transparent'}>
                   <View >
                     <Text style={ styles.labels}>
                       {langs.strings.login_txtTermsAndConditions}
                     </Text>
                   </View>
                 </TouchableHighlight>
                 <View style={styles.fingerPrintLayout}>
                 <TouchableHighlight  underlayColor = {'transparent'}>
                   <View >
                     <Image style={styles.biometricImage} source={biometricImage}/>
                   </View>
                 </TouchableHighlight>
                   <View style={styles.switchRow} >
                   <Text style={ styles.labels} >
                     Enable Finger Print Login
                   </Text>
                     <Switch
                     onValueChange={(value) => this.onSwitchToggle(value) }
                     style={styles.switchControl}
                     value={this.state.falseSwitchIsOn} />
                   </View>
                   <Text>{this.state.message}</Text>
                 </View>

               </Image>
               <WebServiceCallManager visible={false} nav = {this.props.navigation} ref={ (input) => {this.webservicemanager = input;}}/>
             </View>
          );
     }

      fetchCredentials(web,resHandler) {
       if(this.state.phase === 'success') {
        Fingerprint.fetchCredentials(
          (...res) => {
              console.log(res);
              var params = {
                  "Password": res[1],
                  "UserName": res[0],
                  "LoginType": 'Biometric'
             };
             this.setState({username:params.UserName,password:params.Password,phase:''})
             this.webservicemanager.callWebService("LOGIN","TRANSACTION",params,(response) => {this.handleWebServiceCallResponse(response);},
             (err)=> {
             this.authenticate();});
            },
            (res) => {
                console.log(res);
                return null;
              }
        );
     }
   }

} // end of class
  相关解决方案