Android 如何每隔x分钟从api获取
我想在android上每隔x分钟运行一次fetch(使用React native) 我使用了文档中的示例,因为我还不确定如何进行这种获取Android 如何每隔x分钟从api获取,android,react-native-android,Android,React Native Android,我想在android上每隔x分钟运行一次fetch(使用React native) 我使用了文档中的示例,因为我还不确定如何进行这种获取 我甚至不知道我该如何开始(也许是做一个android原生处理器?)。我只找到了一个组件,但它是用于ios的您必须在获取回调的位置设置时间 ComponentWillMount() { AsyncStorage.getItem('accessToken').then((token) => { this.setState({
我甚至不知道我该如何开始(也许是做一个android原生处理器?)。我只找到了一个组件,但它是用于ios的您必须在获取回调的位置设置时间
ComponentWillMount() {
AsyncStorage.getItem('accessToken').then((token) => {
this.setState({
isLoading: false,
time :5000
});
});
},
您可以创建一个AsyncTask(后台线程),从url获取json并在计时器循环中调用它,如下所示:
异步任务:
private class FetchAPI extends AsyncTask<String, String, String> {
BufferedReader reader;
HttpURLConnection conn;
@Override
protected String doInBackground(String... params) {
String data = null;
try {
// Defined URL where to send data
URL url = new URL(YOURURL);
conn = (HttpURLConnection) url.openConnection();
conn.connect();
// Get the server response
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// conn.disconnect();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String result) {
try {
StringBuilder sb = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
String serverResponse = sb.toString(); //Your JSON
} catch (IOException e) {
e.printStackTrace();
}
}
}
此代码将调用FetchAPI方法,该方法使用后台线程从URL获取json。当你得到了JSON,你可以用它做你想做的事情。该方法每5秒调用一次。根据需要编辑“5000”(间隔毫秒)
我希望这能帮助你和/或引导你朝正确的方向前进如果你想在后台运行你的服务,那么你只有一个选择,那就是headless js或基于headless js的npm
componentDidMount(){
this.timer = setInterval(()=> this.getMovies(), 1000)
}
async getMovies(){
fetch('https://facebook.github.io/react-native/movies.json', {method: "GET"})
.then((response) => response.json())
.then((responseData) =>
{
//set your data here
console.log(responseData);
})
.catch((error) => {
console.error(error);
});
}
无头基本服务的最小周期频率不得低于15
如果需要在5分钟内运行服务,那么您可以结合使用headless js和setinterval,如
BackgroundTask.define(async () => { //headless based runs every 15 minute
console.log('headless js service start')
this._interval = setInterval(() => {
console.log('setinterval for 5 minute start')
// Your code
}, 300000);
BackgroundTask.finish()
})
然后在您的任何组件方法(如componentwillmount)中,您需要安排后台任务,如
componentDidMount() {
BackgroundTask.schedule({
period: 900, // Aim to run every 15mins
})
}
您可以单独使用setinterval而不使用headless JS,但将被android停止以节省电池/资源
注意:要测试这些东西,你必须使用真实设备作为物理设备进入睡眠模式,或者像停止后台应用程序这样做,以节省电池/资源,这与模拟器不同我参加聚会有点晚,但我必须做类似的事情。我向一台服务器发出了一个API请求,该服务器获取一系列位置,进行一些计算,并将数据传递给应用程序另一部分中的回调函数,以更新地图。我想让它每“x”秒运行一次。这就是我所做的: 我创建了一个自定义钩子,我从地图屏幕调用它。我想返回两个状态(businessLocations,error)。我在文件顶部创建了一个计时器,如下所示:
const [render, setRender] = useState(false);
useEffect(() => {
setTimeout(() => {
setRender(!render);
}, 20000);
}, [isScreenFocused, render]);
const fetching = useRef(false);
useEffect(() => {
const searchForLocations = async () => {
fetching.current = true;
await requestAllLocations()
.then((locations) => {
const results = locations.map(loc => {
return createBusinessFromAPI(loc);
});
setBusinessLocations(results);
locationsCallback(results);
fetching.current = false;
}).catch((error) => {
fetching.current = false;
throw error;
});
};
if (!fetching.current) {
searchForLocations().catch(error => setError(error));
}
}, [isScreenFocused, render]);
每次聚焦屏幕或更改渲染状态时,都会重新创建此选项。如您所见,我会在每次20秒结束时触发渲染状态更改,从而导致计时器重新启动
在useffect
调用下面,我创建了第二个useffect
调用,如下所示:
const [render, setRender] = useState(false);
useEffect(() => {
setTimeout(() => {
setRender(!render);
}, 20000);
}, [isScreenFocused, render]);
const fetching = useRef(false);
useEffect(() => {
const searchForLocations = async () => {
fetching.current = true;
await requestAllLocations()
.then((locations) => {
const results = locations.map(loc => {
return createBusinessFromAPI(loc);
});
setBusinessLocations(results);
locationsCallback(results);
fetching.current = false;
}).catch((error) => {
fetching.current = false;
throw error;
});
};
if (!fetching.current) {
searchForLocations().catch(error => setError(error));
}
}, [isScreenFocused, render]);
正如您在这里看到的,我使用hookuseRef
(在不同的渲染中不会改变)来确定最后一个请求是否仍在处理中。如果是,我不会在这个渲染周期中调用searchForLocations()
,而只是等待下一个渲染周期。您还可以看到,整个useffect
调用是在计时器启动时触发的,因为我在这里也将渲染状态用作依赖项
这可能不是一个完美的解决方案。我目前正在尝试对它进行一点改进。但是,到目前为止,它对我很有效
以下是整个文件:
import React, {useEffect, useRef, useState} from 'react';
import {requestAllLocations} from '../api/requests';
import {createBusinessFromAPI} from '../model/BusinessCreator';
export default (isScreenFocused, locationsCallback) => {
const [businessLocations, setBusinessLocations] = useState([]);
const [error, setError] = useState(null);
const [render, setRender] = useState(false);
const fetching = useRef(false);
useEffect(() => {
setTimeout(() => {
setRender(!render);
}, 20000);
}, [isScreenFocused, render]);
useEffect(() => {
const searchForLocations = async () => {
fetching.current = true;
await requestAllLocations()
.then((locations) => {
const results = locations.map(loc => {
return createBusinessFromAPI(loc);
});
setBusinessLocations(results);
locationsCallback(results);
fetching.current = false;
}).catch((error) => {
fetching.current = false;
throw error;
});
};
if (!fetching.current) {
searchForLocations().catch(error => setError(error));
}
}, [isScreenFocused, render]);
return [businessLocations, error];
};
好的,这是有道理的。但是我如何在后台运行计时器呢?我有类似的东西。或者我必须使用android本机方法我想你必须一次从api加载数据,然后根据你的业务需要显示。为什么我要问这个问题,是因为我需要每X分钟检查一次更改。所以,假设在这些时间间隔内,一个值大于另一个值。一条消息将出现在用户屏幕上。我想现在我将知道如何应对本机调用本机函数,并尝试使其工作。感谢您的代码应用程序在20-30秒后崩溃。我为一个因此问题而受阻的朋友问了这个问题,他在一小时前设法解决了。非常感谢您的回复。这不是解决方案。它将一直等到第一次抓取完成。我想我有办法确保最后一次抓取已经完成。见下面我的答案。希望它能帮助我成功地使用这种方法。唯一需要注意的是,在第一个
useffect
中调用setRender
之前,需要检查组件是否已装入。我遇到了无法获得操作的问题,因为超时功能将被安排在我的组件卸载后运行。我使用中概述的方法修复了它