问:
Generic base class method for handling service calls in React-Native
Target:

a generic method which calls a web service throgh my Network class shows spinner meanwhile remove it once completed, then finally handles error if any by showing alert otherwise send back the response into my calling class.

What I have done:
I have written following method i.e. in my base class and all classes will have this method.

Problem:
As the setState is called which updates the screen hence any of the alert (error/success) which comes for a moment and then the last screen comes in front and every thing stuck as the alert is behind the screen.

Require:
Can anyone points me what mistake I am doing or any concept how to handle this.

```<code>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')
      }
      )
     }
}
</code>```

2nd Approach
I have adopted this second approach but getting same results here.

```<code>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)
    }
    }
</code>```

答:
My current working class , few classes are custom classes like Screens,SessionManager,SessionTimer,Constants

```<code>"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'/>
    }
}
</code>```

EDIT 16 Sep 2019:

Here I am adding another class where I have made use of my network class defined above, actually its a component in React world so inside render method we have added this component and got reference of that component upon which we are calling a method callWebService()

```<code>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
</code>```

Body:
Target:

a generic method which calls a web service throgh my Network class shows spinner meanwhile remove it once completed, then finally handles error if any by showing alert otherwise send back the response into my calling class.

What I have done:
I have written following method i.e. in my base class and all classes will have this method.

Problem:
As the setState is called which updates the screen hence any of the alert (error/success) which comes for a moment and then the last screen comes in front and every thing stuck as the alert is behind the screen.

Require:
Can anyone points me what mistake I am doing or any concept how to handle this.

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')
      }
      )
     }
}

2nd Approach
I have adopted this second approach but getting same results here.

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)
    }
    }

Body:
My current working class , few classes are custom classes like 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'/>
    }
}

EDIT 16 Sep 2019:

Here I am adding another class where I have made use of my network class defined above, actually its a component in React world so inside render method we have added this component and got reference of that component upon which we are calling a method 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

ContentLicense: CC BY-SA 4.0


来源: stackexchange

问:
How to get Y axis label in android mpchart?
I have plotted graph with corresponding X and Y axis.

Now how to get Y axis label and compare and place another label in Y axis.

For eg:

Y axis label which I got is 1,2,3,4,5 and so on. Now How to assign for corresponding label as,

If it's 2, then low.
If it's 10, then high.
If it's 15, then very high.
and then above all are supreme.

So my question is how to get Y axis label and then change and assign it?
Is it possible to use strings in y axis?

For eg:

Instead of 2 in left and right y axis, I need to display as Low on Y axis. and also how to remove number in displayed graph? ie 2.00

Here is piece of code.

```<code>  List<BarEntry> entries = new ArrayList<>();
    ArrayList<String> labels = new ArrayList<String>();
    mDetectiveGraphExecutor = new DetectiveGraphExecutor(this);
    barChart = (BarChart) findViewById(R.id.chart);
    YAxis leftAxis = barChart.getAxisRight();
    leftAxis.removeAllLimitLines();
    barChart.setDescription("");
    leftAxis.setEnabled(false);
    ViewPortHandler handlers = barChart.getViewPortHandler();
    handlers.setMaximumScaleX(10);
entries.add(new BarEntry(activities.size(), ++columnIndex)); //list of datas displaying..
        labels.add("Time");
        BarDataSet dataset = new BarDataSet(entries, "# Counts");
        BarData data = new BarData(labels, dataset);
        barChart.setData(data);
</code>```

答:
If you need change the value in y axis then use this code </p>

```<code>YAxis yAxis = water_graph.getAxisLeft();//for left side value changes

YAxis yAxis = water_graph.getAxisRight(); //for right side value changes

     yAxis.setGranularityEnabled(true);
     yAxis.setValueFormatter(new IAxisValueFormatter() {
            @Override
            public String getFormattedValue(float value, AxisBase axis) {
                String str="";
                if(value<5)
                    str="Low";
                else if(value<10)
                    str="Medium";
                else if(value==10)
                    str="high";
                else
                    str="very high";
                return str;
            }
        });
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I have plotted graph with corresponding X and Y axis.

Now how to get Y axis label and compare and place another label in Y axis.

For eg:

Y axis label which I got is 1,2,3,4,5 and so on. Now How to assign for corresponding label as,

If it's 2, then low.
If it's 10, then high.
If it's 15, then very high.
and then above all are supreme.

So my question is how to get Y axis label and then change and assign it?
Is it possible to use strings in y axis?

For eg:

Instead of 2 in left and right y axis, I need to display as Low on Y axis. and also how to remove number in displayed graph? ie 2.00

Here is piece of code.

  List<BarEntry> entries = new ArrayList<>();
    ArrayList<String> labels = new ArrayList<String>();
    mDetectiveGraphExecutor = new DetectiveGraphExecutor(this);
    barChart = (BarChart) findViewById(R.id.chart);
    YAxis leftAxis = barChart.getAxisRight();
    leftAxis.removeAllLimitLines();
    barChart.setDescription("");
    leftAxis.setEnabled(false);
    ViewPortHandler handlers = barChart.getViewPortHandler();
    handlers.setMaximumScaleX(10);
entries.add(new BarEntry(activities.size(), ++columnIndex)); //list of datas displaying..
        labels.add("Time");
        BarDataSet dataset = new BarDataSet(entries, "# Counts");
        BarData data = new BarData(labels, dataset);
        barChart.setData(data);

Body:
If you need change the value in y axis then use this code

YAxis yAxis = water_graph.getAxisLeft();//for left side value changes

YAxis yAxis = water_graph.getAxisRight(); //for right side value changes

     yAxis.setGranularityEnabled(true);
     yAxis.setValueFormatter(new IAxisValueFormatter() {
            @Override
            public String getFormattedValue(float value, AxisBase axis) {
                String str="";
                if(value<5)
                    str="Low";
                else if(value<10)
                    str="Medium";
                else if(value==10)
                    str="high";
                else
                    str="very high";
                return str;
            }
        });


问:
Mixing Spring Data Envers and QueryDSL
I'm using a global custom repository in my project which extends QueryDslJpaRepository:

```<code>   public class CustomPagingAndSortingRepositoryImpl<T, ID extends Serializable> extends QueryDslJpaRepository<T, ID>
    implements CustomPagingAndSortingRepository<T, ID> {
</code>```

And the interface:

```<code>   public interface CustomPagingAndSortingRepository<T, ID extends Serializable>
    extends JpaRepository<T, ID>, QueryDslPredicateExecutor<T> {
</code>```

And then on my configuration I annotate it with:

```<code>@EnableJpaRepositories(repositoryBaseClass = CustomPagingAndSortingRepositoryImpl.class)
</code>```

All is working fine, but now I was trying to add auditing support to my entities by using spring-data-envers and according to the docs I should use a specific repository factory bean class :

```<code>@EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class, repositoryBaseClass = CustomPagingAndSortingRepositoryImpl.class)
</code>```

Now obviously if I do this things won't work because my repositories will now be created through the EnversRevisionRepositoryFactoryBean class and will no longer be of CustomPagingAndSortingRepositoryImpl type.

How can I support something like this? I'm not seeing how since my custom repository need to extend from QueryDslJpaRepository already.

答:
I think the relevant part for you is this method of EnversRevisionRepositoryFactoryBean:

```<code>@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
    return EnversRevisionRepositoryImpl.class;
}
</code>```

Here you really want your CustomPagingAndSortingRepositoryImpl returned. So I would try the following:

extend EnversRevisionRepositoryFactoryBean and overwrite getRepositoryBaseClass to return your CustomPagingAndSortingRepositoryImpl.

Make CustomPagingAndSortingRepositoryImpl extend EnversRevisionRepositoryImpl.

Title: Mixing Spring Data Envers and QueryDSL

Body:
I'm using a global custom repository in my project which extends QueryDslJpaRepository:

   public class CustomPagingAndSortingRepositoryImpl<T, ID extends Serializable> extends QueryDslJpaRepository<T, ID>
    implements CustomPagingAndSortingRepository<T, ID> {

And the interface:

   public interface CustomPagingAndSortingRepository<T, ID extends Serializable>
    extends JpaRepository<T, ID>, QueryDslPredicateExecutor<T> {

And then on my configuration I annotate it with:

@EnableJpaRepositories(repositoryBaseClass = CustomPagingAndSortingRepositoryImpl.class)

All is working fine, but now I was trying to add auditing support to my entities by using spring-data-envers and according to the docs I should use a specific repository factory bean class :

@EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class, repositoryBaseClass = CustomPagingAndSortingRepositoryImpl.class)

Now obviously if I do this things won't work because my repositories will now be created through the EnversRevisionRepositoryFactoryBean class and will no longer be of CustomPagingAndSortingRepositoryImpl type.

How can I support something like this? I'm not seeing how since my custom repository need to extend from QueryDslJpaRepository already.

Body:
I think the relevant part for you is this method of EnversRevisionRepositoryFactoryBean:

@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
    return EnversRevisionRepositoryImpl.class;
}

Here you really want your CustomPagingAndSortingRepositoryImpl returned. So I would try the following:

extend EnversRevisionRepositoryFactoryBean and overwrite getRepositoryBaseClass to return your CustomPagingAndSortingRepositoryImpl.

Make CustomPagingAndSortingRepositoryImpl extend EnversRevisionRepositoryImpl.


问:
Layout large amount of Text
so i've got about 100 pages with different Text-Layouts. Bold Fonts in large paragraphs, italic, headlines etc .pp.

Now i'm wondering whats the best way to display them in my uiview. i cannot find an element that fits for me (UILable, Textfield, etc).

Whats the best way to do this? any ideas?

thanks for all hints!

答: If the load time is really long, you should take a look at CATiledLayer. It is used (most probably) on Safari.app or Maps.app to load information on screen lazily

ContentLicense: CC BY-SA 2.5

Title: Layout large amount of Text


问:
In Batch, using FIND or FINDSTR and saving its output to a variable with SET
I have a file that contains a lot of lines, e.g.

```<code>foo=1
foobar=2
bar=3
</code>```

I want to use FIND (or FINDSTR) to read this file and use SET to set a variable foobar to 2, etc.

I would much prefer to only use Batch and tools that come with Windows - no third-party tools. But if it's impossible without any, then I'm open to using them.

答:
Since you've mentioned tools that come with Windows as an option:

PowerShell offers a simple and flexible solution (file is assumed as the name of the input file):

$settings = ConvertFrom-StringData (Get-Content -Raw file)
```

<p>The command above (executed interactively or from a <code>*.ps1</code> file) reads all <code>=</code>-separated key-value pairs into a single <em>hash table</em>, so you can easily access individual settings on demand; e.g.:</p>

<pre class="lang-powershell prettyprint-override"><code>$settings.foobar  # -> 2
</code>```

Body:
I have a file that contains a lot of lines, e.g.

foo=1
foobar=2
bar=3

I want to use FIND (or FINDSTR) to read this file and use SET to set a variable foobar to 2, etc.

I would much prefer to only use Batch and tools that come with Windows - no third-party tools. But if it's impossible without any, then I'm open to using them.

Body:
Since you've mentioned tools that come with Windows as an option:

PowerShell offers a simple and flexible solution (file is assumed as the name of the input file):

$settings = ConvertFrom-StringData (Get-Content -Raw file)

The command above (executed interactively or from a *.ps1 file) reads all =-separated key-value pairs into a single hash table, so you can easily access individual settings on demand; e.g.:

$settings.foobar  # -> 2


问:
React Navigation Reset Can add parameters?
I am still new to react navigation.
I wish to reset the route information after login successfully. However there is some parameters like login information I wish to pass to the main page.

```<code>import { NavigationActions } from 'react-navigation'

const resetAction = NavigationActions.reset({
  index: 0,
  actions: [
        NavigationActions.navigate({ routeName: 'Profile',
                params:{user:this.state.username}})
      ]
  })
    this.props.navigation.dispatch(resetAction)
</code>```

In the Profile page, I want to get access to the params, so I use this:

```<code>constructor(props){
super(props)
this.state = { username: this.props.navigation.state.params.user,
  }
</code>```

but I received: undefined is not an object (evaluating '_this.props.navigation.state.params.user') in the Console log.
May I know how should I get the parameters? Thank you

答:
You are passing parameters by using username as key.
So when you are retrieving it your code should look like this

Step 1: Pass params

```<code>this.props.navigation.navigate('Your-Screen_name',{ username: 'Lucy' })
</code>```

Step2: Get Params

```<code>this.state = {
    username: this.props.navigation.state.params.username,
}
</code>```

Body:
I am still new to react navigation.
I wish to reset the route information after login successfully. However there is some parameters like login information I wish to pass to the main page.

import { NavigationActions } from 'react-navigation'

const resetAction = NavigationActions.reset({
  index: 0,
  actions: [
        NavigationActions.navigate({ routeName: 'Profile',
                params:{user:this.state.username}})
      ]
  })
    this.props.navigation.dispatch(resetAction)

In the Profile page, I want to get access to the params, so I use this:

constructor(props){
super(props)
this.state = { username: this.props.navigation.state.params.user,
  }

but I received: undefined is not an object (evaluating '_this.props.navigation.state.params.user') in the Console log.
May I know how should I get the parameters? Thank you

Body:
You are passing parameters by using username as key.
So when you are retrieving it your code should look like this

Step 1: Pass params

this.props.navigation.navigate('Your-Screen_name',{ username: 'Lucy' })

Step2: Get Params

this.state = {
    username: this.props.navigation.state.params.username,
}


问:
How to increase fps opencv multi camera setup
I have an OpenCV program that grabs images from 2 cameras at the same time as fast as possible.  In order to get both cameras to take images as close as possible I'm using the grab() and retrieve() functions.  The frame rate I'm getting is pretty slow right now (around 6 fps).  I would like to increase this fps.  Does anyone have any idea on how I can increase the fps?

I was thinking maybe put each camera on a different thread or utilizing multithreading in some way but I am afraid that they won't capture image at the same time that way.

```<code>void takeImages(VideoCapture& cap, VideoCapture& cap1, int imagecount){

    if(!cap.isOpened()|| !cap1.isOpened()) {  // check if we succeeded
        cout << "Can not open cameras." << endl;
        return;
    }

    Mat frame, frame2;
    for(int x = 0;x < imagecount; x++)
    {
        // Capture image from both camera at the same time (important).
        if( !cap.grab() || !cap1.grab() )
        {

            cout << "Can not grab images." << endl;
            return;
        }

        if( cap.retrieve(frame,3) || cap1.retrieve(frame,3)){

            //process images here..

        } else {
            cout << "Can not retrieve images." << endl;
            return;
        }

        printf("x = %d\n", x);
    }

    waitKey(0);
}

int main(int, char**)
{

    // trying to set higher program priority to increase fps here
    cout << "Nice = " << nice(21) << endl;

    VideoCapture cap(0); // open the default camera
    VideoCapture cap1(1);

    namedWindow("cam1",1);
    namedWindow("cam2",1);

    std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
    //Get the time it takes to get 200 frames from BOTH cameras.
    takeImages(cap,cap1, 200);

    std::chrono::steady_clock::time_point end= std::chrono::steady_clock::now();
    std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::seconds>(end - begin).count() <<std::endl;

    return 0;
}
</code>```

答:
You should be able to double your fps by moving each camera to its own thread. To synchronize the cameras you can use the std::chrono::steady_clock to make sure they capture at the same time.

Maybe something like this:

```<code>#include <thread>

using steady_clock = std::chrono::steady_clock;

void takeImages(VideoCapture& cap, int imagecount,
    steady_clock::time_point next_frame, unsigned fps)
{
    assert(fps > 0);
    assert(fps <= 1000);

    Mat frame;
    for(int x = 0; x  < imagecount; x++)
    {
        // Capture image from both camera at the same time (important).
        std::this_thread::sleep_until(next_frame);
        next_frame += std::chrono::milliseconds(1000 / fps);

        if(!cap.grab())
            throw std::runtime_error("Can not grab image.");

        if(!cap.retrieve(frame, 3))
            throw std::runtime_error("Can not retrieve image.");

        // process image here

    }

    waitKey(0);
}

int main(int, char**)
{
    try
    {
        // trying to set higher program priority to increase fps here
        // cout << "Nice = " << nice(21) << endl;

        VideoCapture cap0(0); // open the default camera
        VideoCapture cap1(1 + CAP_V4L2);

        if(!cap0.isOpened() || !cap1.isOpened())
        {  // check if we succeeded
            cout << "Can not open cameras." << endl;
            return EXIT_FAILURE;
        }

//      namedWindow("cam1", WINDOW_AUTOSIZE);
//      namedWindow("cam2", WINDOW_AUTOSIZE);

        std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();

        // pass the same time point to both threads to synchronize their
        // frame start times
        steady_clock::time_point next_frame = steady_clock::now() + std::chrono::milliseconds(50);

        std::thread t1{takeImages, std::ref(cap0), 200, next_frame, 10};
        std::thread t2{takeImages, std::ref(cap1), 200, next_frame, 10};

        t1.join();
        t2.join();

        std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
        std::cout << "Time difference = "
            << std::chrono::duration_cast<std::chrono::seconds>(end - begin).count()
            << std::endl;
    }
    catch(std::exception const& e)
    {
        std::cerr << e.what() << '\n';
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
</code>```

Body:
I have an OpenCV program that grabs images from 2 cameras at the same time as fast as possible.  In order to get both cameras to take images as close as possible I'm using the grab() and retrieve() functions.  The frame rate I'm getting is pretty slow right now (around 6 fps).  I would like to increase this fps.  Does anyone have any idea on how I can increase the fps?

I was thinking maybe put each camera on a different thread or utilizing multithreading in some way but I am afraid that they won't capture image at the same time that way.

void takeImages(VideoCapture& cap, VideoCapture& cap1, int imagecount){

    if(!cap.isOpened()|| !cap1.isOpened()) {  // check if we succeeded
        cout << "Can not open cameras." << endl;
        return;
    }

    Mat frame, frame2;
    for(int x = 0;x < imagecount; x++)
    {
        // Capture image from both camera at the same time (important).
        if( !cap.grab() || !cap1.grab() )
        {

            cout << "Can not grab images." << endl;
            return;
        }

        if( cap.retrieve(frame,3) || cap1.retrieve(frame,3)){

            //process images here..

        } else {
            cout << "Can not retrieve images." << endl;
            return;
        }

        printf("x = %d\n", x);
    }

    waitKey(0);
}

int main(int, char**)
{

    // trying to set higher program priority to increase fps here
    cout << "Nice = " << nice(21) << endl;

    VideoCapture cap(0); // open the default camera
    VideoCapture cap1(1);

    namedWindow("cam1",1);
    namedWindow("cam2",1);

    std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
    //Get the time it takes to get 200 frames from BOTH cameras.
    takeImages(cap,cap1, 200);

    std::chrono::steady_clock::time_point end= std::chrono::steady_clock::now();
    std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::seconds>(end - begin).count() <<std::endl;

    return 0;
}

Body:
You should be able to double your fps by moving each camera to its own thread. To synchronize the cameras you can use the std::chrono::steady_clock to make sure they capture at the same time.

Maybe something like this:

#include <thread>

using steady_clock = std::chrono::steady_clock;

void takeImages(VideoCapture& cap, int imagecount,
    steady_clock::time_point next_frame, unsigned fps)
{
    assert(fps > 0);
    assert(fps <= 1000);

    Mat frame;
    for(int x = 0; x  < imagecount; x++)
    {
        // Capture image from both camera at the same time (important).
        std::this_thread::sleep_until(next_frame);
        next_frame += std::chrono::milliseconds(1000 / fps);

        if(!cap.grab())
            throw std::runtime_error("Can not grab image.");

        if(!cap.retrieve(frame, 3))
            throw std::runtime_error("Can not retrieve image.");

        // process image here

    }

    waitKey(0);
}

int main(int, char**)
{
    try
    {
        // trying to set higher program priority to increase fps here
        // cout << "Nice = " << nice(21) << endl;

        VideoCapture cap0(0); // open the default camera
        VideoCapture cap1(1 + CAP_V4L2);

        if(!cap0.isOpened() || !cap1.isOpened())
        {  // check if we succeeded
            cout << "Can not open cameras." << endl;
            return EXIT_FAILURE;
        }

//      namedWindow("cam1", WINDOW_AUTOSIZE);
//      namedWindow("cam2", WINDOW_AUTOSIZE);

        std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();

        // pass the same time point to both threads to synchronize their
        // frame start times
        steady_clock::time_point next_frame = steady_clock::now() + std::chrono::milliseconds(50);

        std::thread t1{takeImages, std::ref(cap0), 200, next_frame, 10};
        std::thread t2{takeImages, std::ref(cap1), 200, next_frame, 10};

        t1.join();
        t2.join();

        std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
        std::cout << "Time difference = "
            << std::chrono::duration_cast<std::chrono::seconds>(end - begin).count()
            << std::endl;
    }
    catch(std::exception const& e)
    {
        std::cerr << e.what() << '\n';
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}


问:
How do I list the hot links of a subreddit via PowerShell?
What's a good way to retrieve subreddit links via API in PowerShell?</p>

答:
Reddit serves content by JSON if you put <code>.json</code> on the end of a URI, and PowerShell can use that. Hot links on /r/programming : </p>

```<code>(irm https://www.reddit.com/r/programming/hot/.json).data.children.data | select score, subreddit, title, url
</code>```

Body:
Reddit serves content by JSON if you put .json on the end of a URI, and PowerShell can use that. Hot links on /r/programming :

(irm https://www.reddit.com/r/programming/hot/.json).data.children.data | select score, subreddit, title, url


问:
how to include multiple layout in single xml file and use in single activity
I had the api response code which has 20 datas, in which 10 data is displayed in one layout1 and 5 data need to display in another layout2 using next button click in layout1 and 5 data need to display in another layout3 using next button. these all need to be happen in single activity.

I am new in android, please tell the functions or useful links.

答:
You can use Model Class of the response to store the data. Then user ViewPager OR Fragments in one activity to show the data.

Here is an example of Model Class with demo response:

```<code>{
  "businesses": [
    {
      "id": "yelp-tropisueno",
      "name" : "Tropisueno",
      "display_phone": "+1-415-908-3801",
      "image_url": "http://s3-media2.ak.yelpcdn.com/bphoto/7DIHu8a0AHhw-BffrDIxPA/ms.jpg"
    }
  ]
}
</code>```

Code of Model Class:

```<code>public class Business {
private String id;
private String name;
private String phone;
private String imageUrl;

public String getName() {
    return this.name;
}

public String getPhone() {
    return this.phone;
}

public String getImageUrl() {
    return this.imageUrl;
}
}
</code>```

Here are the links which will be help you:

http://pojo.sodhanalibrary.com/Convert

https://developer.android.com/guide/components/fragments.html

https://developer.android.com/training/animation/screen-slide.html

Body:
You can use Model Class of the response to store the data. Then user ViewPager OR Fragments in one activity to show the data.

Here is an example of Model Class with demo response:

{
  "businesses": [
    {
      "id": "yelp-tropisueno",
      "name" : "Tropisueno",
      "display_phone": "+1-415-908-3801",
      "image_url": "http://s3-media2.ak.yelpcdn.com/bphoto/7DIHu8a0AHhw-BffrDIxPA/ms.jpg"
    }
  ]
}

Code of Model Class:

public class Business {
private String id;
private String name;
private String phone;
private String imageUrl;

public String getName() {
    return this.name;
}

public String getPhone() {
    return this.phone;
}

public String getImageUrl() {
    return this.imageUrl;
}
}

Here are the links which will be help you:

http://pojo.sodhanalibrary.com/Convert

https://developer.android.com/guide/components/fragments.html

https://developer.android.com/training/animation/screen-slide.html


问:
How to retrieve information of a record when we click on the submit button assigned to each row using jsp and servlets
I have retrieved table information from mysql by creating pogoclass.jsp and servlet and printed it using jstl in jsp. My problem is I am not able to retrieve each row information when I click on the submit button assigned to each row and send it to another jsp to update the row. I am using eclipseIDE. Here is my code:

index.jsp:

```<code><%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form action="ViewTableDelete" method="post">
        <table>
            <tr>
                <td><input type="submit" value="tablevalues" /></td>
                </tr>
          </table>
    </form>
</body>
</html>
</code>```

pojoclassdemo3.java:

```<code>package com.example.pojo;

public class PojoClassDemo3 {

    private String empname;
    private String password;

    public PojoClassDemo3()
    {

    }

    public String getEmpname() {
        return empname;
    }

    public void setEmpname(String empname) {
        this.empname = empname;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "PojoClassDemo3 [empname=" + empname + ", password=" + password + "]";
    }

}
</code>```

viewTableDelete.java:

```<code>import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.example.pojo.PojoClassDemo3;

/**
 * Servlet implementation class ViewTableDelete
 */
@WebServlet("/ViewTableDelete")
public class ViewTableDelete extends HttpServlet {
    Connection con;
    Statement st;
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public ViewTableDelete() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see Servlet#init(ServletConfig)
     */
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub
        System.out.println("********** In Init method **************");
        try {
            Class.forName("com.mysql.jdbc.Driver");
            System.out.println("registered");
            con = DriverManager.getConnection("jdbc:mysql://localhost:3306/emp1", "root", "root");
            System.out.println("connection established");
            st = con.createStatement();
            System.out.println("statement created");
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    /**
     * @see Servlet#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub

    }

    /**
     * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
     */
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        // TODO Auto-generated method stub
        try{
            PrintWriter out=response.getWriter();
            response.setContentType("text/html");
            ResultSet rs=st.executeQuery("select * from emp1.employee");
            System.out.println("select * from emp1.employee");
            System.out.println("creating list");
            List<PojoClassDemo3> list = new ArrayList<PojoClassDemo3>();
            while(rs.next())
            {
                PojoClassDemo3  pojoclassdemo=new  PojoClassDemo3();
                pojoclassdemo.setEmpname(rs.getString("empname"));
                pojoclassdemo.setPassword(rs.getString("password"));
                list.add(pojoclassdemo);

            }

            request.setAttribute("list",list);
            RequestDispatcher rd= request.getRequestDispatcher("tableprint3.jsp");
            rd.forward(request, response);

        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }

    }

}
</code>```

tableprint3.jsp:

```<code><%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
    <%@page import="java.util.List"%>
     <%@page import="java.util.Map"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>

</head>
<body >
<form method="post" action="update.jsp">
        <table border="1" cellspacing="0" cellpadding="5">
            <tr>
                <th>empname</th>
                <th>password</th>
                <th>edit</th>
            </tr>

            <c:forEach items="${requestScope.list}" var="record">

                <tr>
                    <td><input type="text" value="${record.empname}" /></td>
                    <td><input type="text" value="${record.password}" /></td>
                    <td><input type="submit" name="${record.empname}" onclick="Change(name)" value="update" /></td>

         </c:forEach>

        </table>
    </form>

</body>
</html>
</code>```

答:
You should add a name field for each textboxes and need to a hidden field of the record to be updated ex.

```<code>            <tr>
                <td><input name="empname" type="text" value="${record.empname}" /></td>
                <td><input name="password" type="text" value="${record.password}" /></td>
                <td><input type="submit" name="${record.empname}" onclick="Change(name)" value="update" /></td>

     </c:forEach>
</code>```

Body:
I have retrieved table information from mysql by creating pogoclass.jsp and servlet and printed it using jstl in jsp. My problem is I am not able to retrieve each row information when I click on the submit button assigned to each row and send it to another jsp to update the row. I am using eclipseIDE. Here is my code:

index.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>

<form action="ViewTableDelete" method="post">

                <input type="submit" value="tablevalues" />

    </form>

pojoclassdemo3.java:

package com.example.pojo;

public class PojoClassDemo3 {

    private String empname;
    private String password;

    public PojoClassDemo3()
    {

    }

    public String getEmpname() {
        return empname;
    }

    public void setEmpname(String empname) {
        this.empname = empname;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "PojoClassDemo3 [empname=" + empname + ", password=" + password + "]";
    }

}

viewTableDelete.java:

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.example.pojo.PojoClassDemo3;

/**
 * Servlet implementation class ViewTableDelete
 */
@WebServlet("/ViewTableDelete")
public class ViewTableDelete extends HttpServlet {
    Connection con;
    Statement st;
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public ViewTableDelete() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see Servlet#init(ServletConfig)
     */
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub
        System.out.println("********** In Init method **************");
        try {
            Class.forName("com.mysql.jdbc.Driver");
            System.out.println("registered");
            con = DriverManager.getConnection("jdbc:mysql://localhost:3306/emp1", "root", "root");
            System.out.println("connection established");
            st = con.createStatement();
            System.out.println("statement created");
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    /**
     * @see Servlet#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub

    }

    /**
     * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
     */
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        // TODO Auto-generated method stub
        try{
            PrintWriter out=response.getWriter();
            response.setContentType("text/html");
            ResultSet rs=st.executeQuery("select * from emp1.employee");
            System.out.println("select * from emp1.employee");
            System.out.println("creating list");
            List<PojoClassDemo3> list = new ArrayList<PojoClassDemo3>();
            while(rs.next())
            {
                PojoClassDemo3  pojoclassdemo=new  PojoClassDemo3();
                pojoclassdemo.setEmpname(rs.getString("empname"));
                pojoclassdemo.setPassword(rs.getString("password"));
                list.add(pojoclassdemo);

            }

            request.setAttribute("list",list);
            RequestDispatcher rd= request.getRequestDispatcher("tableprint3.jsp");
            rd.forward(request, response);

        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }

    }

}

tableprint3.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
    <%@page import="java.util.List"%>
     <%@page import="java.util.Map"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>

<form method="post" action="update.jsp">

                empname
                password
                edit

            <c:forEach items="${requestScope.list}" var="record">

                    <input type="text" value="${record.empname}" />
                    <input type="text" value="${record.password}" />
                    <input type="submit" name="${record.empname}" onclick="Change(name)" value="update" />

         </c:forEach>

    </form>

Body:
You should add a name field for each textboxes and need to a hidden field of the record to be updated ex.

            <tr>
                <td><input name="empname" type="text" value="${record.empname}" /></td>
                <td><input name="password" type="text" value="${record.password}" /></td>
                <td><input type="submit" name="${record.empname}" onclick="Change(name)" value="update" /></td>

     </c:forEach>


问:
Failed to create provisioning profile
I'm trying to create a project in Xcode, Version 8.0 beta 6 (8S201h) and I'm getting this error.

The apple account is a free one because I'm just playing around with Xcode but it is forcing me to set it as a Team. Any help?

答:
Check these things.

1.A device is connected to your system or not.

2.Deployment target in xcode. (General->Deployment info->Deployment target)
It should match with the ios version of your device.

3.Change your bundle identifier. Follow general rules of setting a unique bundle identifier for yourproject while running in device.
See this what is correct format of bundle identifier in iOS?

Also be careful with the number of bundle identifiers you set in the project. Please remember all bundle identifiers or note it down somewhere. Since you are using a free account you have limited access to the number of bundle id's.

You should also disable push notifications in the "Capabilities" section of the project. Try changing "App groups" as well in the format of group.com.someString.

These things helped me run my app in real device without any errors.

Title: Failed to create provisioning profile


问:
Interpreting internal features of Multiplayer Perceptrons
I've trained a multiplayer perceptron on a medical imaging classification task (classifying whether an ultrasound scanning image belongs to the healthy or disease condition). The network consists of 2 fully connected hidden layers and 1 output unit. I then want to examine the weights to see which features in the images (e.g., clusters of pixels) are the most important for the network to distinguish between different classes. Since my network has two layers of hidden weights, how do I use these weights to quantify the importance of each image pixel? Could someone experienced with this point me to the right literature? Thanks.</p>

答:
"Several methods for finding saliency have been described by other authors. Among them are sensitivity
based approaches [4, 5, 6], deconvolution based ones [7, 8], or more complex ones like
layer-wise relevance propagation (LRP) [9]."

source : https://arxiv.org/pdf/1704.07911.pdf

They are doing what you want, but with a CNN, maybe you should go from a MLP to a CNN, that would seem appropriate for medical imaging classification.

Or maybe this paper would fit better:

Randomization approach for understanding variable contributions in artificial neural networks


问:
How to custom url without change resources?
Our website is rails 4.2.8 and ruby 2.4.1, we have products to sell, so our routes like:

```<code>resources :products
resources :orders, only: [:new, :create, :destroy] do
        collection do
          get :success
          get :fail
          get :details
        end
</code>```

so orders url like: https://example.com/orders/new?params...

but we want add product name on url for tracking purpose, something like:

https://example.com/product_name/orders/new?params...

can I accomplish this without change route resources or controller position?

答:
You have to change the routes like:

```<code>resources :products do
    resources :orders, only: [:new, :create, :destroy] do
        collection do
          get :success
          get :fail
          get :details
    end
end
</code>```

Then you will get the route
https://example.com/product_name/orders/new?params...

Body:
Our website is rails 4.2.8 and ruby 2.4.1, we have products to sell, so our routes like:

resources :products
resources :orders, only: [:new, :create, :destroy] do
        collection do
          get :success
          get :fail
          get :details
        end

so orders url like: https://example.com/orders/new?params...

but we want add product name on url for tracking purpose, something like:

https://example.com/product_name/orders/new?params...

can I accomplish this without change route resources or controller position?

Body:
You have to change the routes like:

resources :products do
    resources :orders, only: [:new, :create, :destroy] do
        collection do
          get :success
          get :fail
          get :details
    end
end

Then you will get the route
https://example.com/product_name/orders/new?params...


问:
Organizing objects with partially shared interface
I've recently come across a couple of situations that I think could be cleaned up with a different design, but I don't know of any patterns that would fit.

In all of these situations, I have a few classes that partially share an API.  For example, a logger class:

```<code>struct ILogger { virtual void log(string msg) = 0; };
struct StdOutLogger : public ILogger {
    void log(string msg) override; // Log to stdout
};
struct FileLogger : public ILogger {
    void log(string msg) override; // Log to file
};
struct GuiLogger : public ILogger {
    void log(string msg) override; // Log to GUI
    void draw();
    void clear();
};
</code>```

or perhaps:

```<code>struct Graphic {
    virtual void draw();
    virtual void setPosition();
    // etc.
};
struct AnimatedGraphic : public Graphic {
    void draw() override;
    void start();
    void stop();
    void setLooping(bool loop);
};
</code>```

Now, depending on who owns these objects, I might have a container of references/pointers to a common interface:

```<code>class LogManager {
    std::vector<std::unique_ptr<ILogger>> _loggers;
    // ...
};
</code>```

Or I might keep the types separated and choose at runtime which one to use:

```<code>// This is already starting to get messy
class SomethingWithGraphic {
    std::unique_ptr<Graphic> _graphic;
    std::unique_ptr<AnimatedGraphic> _animatedGraphic;
    // ...
};
</code>```

The first solution is fine until I need to start using the functionality that is not part of the common interface.  The second solution allows me to choose the one I need, but it is error prone and requires ugly branches everywhere.

I've come up with a couple of alternative solutions, but I haven't found one that really feels right.

Keep one owning container, and create additional containers that point to the owned objects, but through a different interface.  (Requires that the containers be kept in sync)

Add all functions to interface, but leave implementations empty for objects that don't need the extra functions.  (Those functions don't really belong as part of that interface)

Store variants of all potential types.  (Feels like a hack, requires visitors everywhere)

Using the logger example:

```<code>//// 1 ////
struct IDrawable {
    virtual void draw() = 0;
    virtual void clear() = 0;
};
std::vector<std::unique_ptr<ILogger>> _loggers;
std::vector<IDrawable*>               _drawableLoggers;

//// 2 ////
struct ILogger {
    virtual void log(string msg) = 0;
    virtual void draw() {};
    virtual void clear() {};
};
struct StdOutLogger : public ILogger {
    void log(string msg) override; // Log to stdout
};
struct FileLogger : public ILogger {
    void log(string msg) override; // Log to file
};
struct GuiLogger : public ILogger {
    void log(string msg) override; // Log to GUI
    void draw() override;
    void clear() override;
};

//// 3 ////
std::vector<std::variant<StdOutLogger, FileLogger, GuiLogger>> _loggers;
</code>```

#1 seems the most correct I think, but still not the greatest.

Does anyone know of any patterns or structures that could clean this up?

答:
A viable approach: you can use a vector of pointers or references to your interface and implement the visitor pattern for all those cases in which you want to get out of one instance its actual type and call a method that isn't part of the common interface.

Here is a minimal, working example:

```<code>#include<iostream>
#include<memory>
#include<vector>

struct Visitor;

struct Interface {
    virtual void method() = 0;
    virtual void accept(Visitor &) = 0;
};

struct A: Interface {
    void method() override { std::cout << "A::method" << std::endl; }
    void f() { std::cout << "A::f" << std::endl; }
    void accept(Visitor &) override;
};

struct B: Interface {
    void method() override { std::cout << "B::method" << std::endl; }
    void g() { std::cout << "B::g" << std::endl; }
    void accept(Visitor &) override;
};

struct Visitor {
    void visit(A &a) { a.f(); }
    void visit(B &b) { b.g(); }
};

void A::accept(Visitor &v) { v.visit(*this); }
void B::accept(Visitor &v) { v.visit(*this); }

int main() {
    std::vector<std::unique_ptr<Interface>> vec;

    vec.push_back(std::make_unique<A>());
    vec.push_back(std::make_unique<B>());

    Visitor visitor;

    for(auto &&i: vec) {
        i->method();
        i->accept(visitor);
    }
}
</code>```

Body:
I've recently come across a couple of situations that I think could be cleaned up with a different design, but I don't know of any patterns that would fit.

In all of these situations, I have a few classes that partially share an API.  For example, a logger class:

struct ILogger { virtual void log(string msg) = 0; };
struct StdOutLogger : public ILogger {
    void log(string msg) override; // Log to stdout
};
struct FileLogger : public ILogger {
    void log(string msg) override; // Log to file
};
struct GuiLogger : public ILogger {
    void log(string msg) override; // Log to GUI
    void draw();
    void clear();
};

or perhaps:

struct Graphic {
    virtual void draw();
    virtual void setPosition();
    // etc.
};
struct AnimatedGraphic : public Graphic {
    void draw() override;
    void start();
    void stop();
    void setLooping(bool loop);
};

Now, depending on who owns these objects, I might have a container of references/pointers to a common interface:

class LogManager {
    std::vector<std::unique_ptr<ILogger>> _loggers;
    // ...
};

Or I might keep the types separated and choose at runtime which one to use:

// This is already starting to get messy
class SomethingWithGraphic {
    std::unique_ptr<Graphic> _graphic;
    std::unique_ptr<AnimatedGraphic> _animatedGraphic;
    // ...
};

The first solution is fine until I need to start using the functionality that is not part of the common interface.  The second solution allows me to choose the one I need, but it is error prone and requires ugly branches everywhere.

I've come up with a couple of alternative solutions, but I haven't found one that really feels right.

Keep one owning container, and create additional containers that point to the owned objects, but through a different interface.  (Requires that the containers be kept in sync)

Add all functions to interface, but leave implementations empty for objects that don't need the extra functions.  (Those functions don't really belong as part of that interface)

Store variants of all potential types.  (Feels like a hack, requires visitors everywhere)

Using the logger example:

//// 1 ////
struct IDrawable {
    virtual void draw() = 0;
    virtual void clear() = 0;
};
std::vector<std::unique_ptr<ILogger>> _loggers;
std::vector<IDrawable*>               _drawableLoggers;

//// 2 ////
struct ILogger {
    virtual void log(string msg) = 0;
    virtual void draw() {};
    virtual void clear() {};
};
struct StdOutLogger : public ILogger {
    void log(string msg) override; // Log to stdout
};
struct FileLogger : public ILogger {
    void log(string msg) override; // Log to file
};
struct GuiLogger : public ILogger {
    void log(string msg) override; // Log to GUI
    void draw() override;
    void clear() override;
};

//// 3 ////
std::vector<std::variant<StdOutLogger, FileLogger, GuiLogger>> _loggers;

#1 seems the most correct I think, but still not the greatest.

Does anyone know of any patterns or structures that could clean this up?

Body:
A viable approach: you can use a vector of pointers or references to your interface and implement the visitor pattern for all those cases in which you want to get out of one instance its actual type and call a method that isn't part of the common interface.

Here is a minimal, working example:

#include<iostream>
#include<memory>
#include<vector>

struct Visitor;

struct Interface {
    virtual void method() = 0;
    virtual void accept(Visitor &) = 0;
};

struct A: Interface {
    void method() override { std::cout << "A::method" << std::endl; }
    void f() { std::cout << "A::f" << std::endl; }
    void accept(Visitor &) override;
};

struct B: Interface {
    void method() override { std::cout << "B::method" << std::endl; }
    void g() { std::cout << "B::g" << std::endl; }
    void accept(Visitor &) override;
};

struct Visitor {
    void visit(A &a) { a.f(); }
    void visit(B &b) { b.g(); }
};

void A::accept(Visitor &v) { v.visit(*this); }
void B::accept(Visitor &v) { v.visit(*this); }

int main() {
    std::vector<std::unique_ptr<Interface>> vec;

    vec.push_back(std::make_unique<A>());
    vec.push_back(std::make_unique<B>());

    Visitor visitor;

    for(auto &&i: vec) {
        i->method();
        i->accept(visitor);
    }
}


问:
Specify the sdcard application data directory path to logback-android
I am using logback-android in my app for logging. I need to write the log to a file in the application data directory in sdcard. I used below file appender config.

```<code><appender name="file" class="ch.qos.logback.core.FileAppender">
    <file>/sdcard/Android/data/com.my.app/files/app.log</file>
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>
</code>```

It can be seen that I have used following log file location.

/sdcard/Android/data/com.my.app/files/app.log

I also can use log file location like below.

/storage/emulated/0/Android/data/com.my.app/files/app.log

Above path is the path returned by getExternalFilesDir().

But, the example in the project wiki page uses file location in following format.

/data/data/com.example/files/log/foo.log.

Above path format does not work in my case, where earlier two path formats I mentioned did work.

What is the correct way to specify the application data directory path in the logback.xml? Can the directory path vary from the first two patterns I mentioned, in various devices?

答:
I finally decided to set the file path programatically. I added following code to the onCreate() of my custom Application class.

```<code>LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
for (ch.qos.logback.classic.Logger logger : context.getLoggerList()) {
    for (Iterator<Appender<ILoggingEvent>> index = logger.iteratorForAppenders(); index.hasNext(); ) {
        Appender<ILoggingEvent> appender = index.next();
        if (appender instanceof FileAppender) {
            ((FileAppender) appender).setFile(new File(getExternalFilesDir(null), "app.log").getAbsolutePath());
            appender.start();
        }
    }
}
</code>```

Body:
I am using logback-android in my app for logging. I need to write the log to a file in the application data directory in sdcard. I used below file appender config.

<appender name="file" class="ch.qos.logback.core.FileAppender">
    <file>/sdcard/Android/data/com.my.app/files/app.log</file>
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

It can be seen that I have used following log file location.

/sdcard/Android/data/com.my.app/files/app.log

I also can use log file location like below.

/storage/emulated/0/Android/data/com.my.app/files/app.log

Above path is the path returned by getExternalFilesDir().

But, the example in the project wiki page uses file location in following format.

/data/data/com.example/files/log/foo.log.

Above path format does not work in my case, where earlier two path formats I mentioned did work.

What is the correct way to specify the application data directory path in the logback.xml? Can the directory path vary from the first two patterns I mentioned, in various devices?

Body:
I finally decided to set the file path programatically. I added following code to the onCreate() of my custom Application class.

LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
for (ch.qos.logback.classic.Logger logger : context.getLoggerList()) {
    for (Iterator<Appender<ILoggingEvent>> index = logger.iteratorForAppenders(); index.hasNext(); ) {
        Appender<ILoggingEvent> appender = index.next();
        if (appender instanceof FileAppender) {
            ((FileAppender) appender).setFile(new File(getExternalFilesDir(null), "app.log").getAbsolutePath());
            appender.start();
        }
    }
}