Я заполняю несколько элементов, таких как ScrollView, данными из нескольких файлов XML. При нажатии кнопки с сервера загружаются самые последние файлы. Я пытаюсь отобразить их прямо в графическом интерфейсе, но мне всегда приходится перезапускать приложение, чтобы увидеть последнюю загруженную версию. Загрузка и запись работают корректно.
Вот код:
Сначала процесс загрузки/обновления
public bool update() {
try {
// Download + Save
WebClient wc = new WebClient();
wc.Credentials = new NetworkCredential("anonymous", "");
wc.DownloadFile(_address_employeesXML, _filePathToXMLImport + "/employees.xml");
XMLReader test = new XMLReader(logController);
test.readXMLFiles();
Debug.Log("Update successful");
} catch (Exception e) {
#if UNITY_EDITOR
EditorUtility.DisplayDialog("Error", e.Message, "OK");
#endif
XMLReader test = new XMLReader(logController);
//test.readXMLFiles();
Debug.LogException(e);
return false;
}
return true;
}
затем процесс чтения:
public bool readEmployees()
{
string pathToEmployeeXML = _filePathToXMLImport + "/employees.xml";
if (File.Exists(pathToEmployeeXML))
{
using (XmlReader reader = XmlReader.Create(pathToEmployeeXML))
{
while (reader.Read())
{
// Only detect start elements.
if (reader.IsStartElement())
{
switch(reader.Name)
{
case "employee":
XmlReader inner = reader.ReadSubtree();
inner.ReadToDescendant("firstName");
string firstName = inner.ReadElementString();
inner.ReadToDescendant("lastName");
string lastName = inner.ReadElementString();
generateEmployee(firstName, lastName);
break;
}
}
}
}
return true;
}
return false;
}
Я нашел эту тему: Перезагрузка ресурса XML в Unity Что, к сожалению, на самом деле не решает мою проблему.
Я также пытался использовать AssetDatabase.Refresh, но, честно говоря, так и не понял, как это реализовать.
Обновлено:
Итак, теперь я изменил его, чтобы использовать File.IO и загружать файлы асинхронно. Мне все еще нужно перезапустить приложение, чтобы увидеть изменения.
public class XMLController : MonoBehaviour {
public MessageLogsController logController;
public ApplicationStateSaver saver;
const string _address = "ftp://127.0.0.1:2121/";
const string _address_maintenancePlansXML = _address + "maintenancePlans.xml";
const string _address_employeesXML = _address + "employees.xml";
const string _address_materialsXML = _address + "materials.xml";
const string _address_machinesXML = _address + "machines.xml";
const string maintenancePlans = "maintenancePlans";
const string employees = "employees";
const string materials = "materials";
const string machines = "machines";
// Use this for initialization
void Start () {
XMLReader XMLReader = new XMLReader(logController);
StartCoroutine(GetXML(_address_maintenancePlansXML, maintenancePlans));
StartCoroutine(GetXML(_address_employeesXML, employees));
StartCoroutine(GetXML(_address_materialsXML, materials));
StartCoroutine(GetXML(_address_machinesXML, machines));
XMLReader.readXMLFiles();
saver.Initialize();
}
public void WriteInformationToXML()
{
XMLWriter writer = new XMLWriter();
writer.writeXML();
}
IEnumerator GetXML(string link, string file_name) {
UnityWebRequest www = UnityWebRequest.Get(link);
yield return www.SendWebRequest();
Debug.Log("Success");
if (www.isNetworkError || www.isHttpError) {
Debug.Log(www.error);
}
else {
// Show results as text
Debug.Log(www.downloadHandler.text);
string savePath = string.Format("{0}/{1}.xml", Application.persistentDataPath + "/Files/XML/Import/", file_name);
System.IO.File.WriteAllText(savePath, www.downloadHandler.text);
Debug.Log("Files written");
}
}
Я добавил немного кода. Я просто пропускаю существующую функцию, которая помогает перезагружать холст/определенные активы без перезапуска приложения.





Я бы предпочел сделать весь процесс асинхронным, чтобы не блокировать основной поток, используя UnityWebRequest для загрузки.
На самом деле вам не нужно писать в файл и читать его снова ... вы можете напрямую использовать загруженный string и передать его в XmlSerializer (вы должны реализовать класс, представляющий макет xml - см. Сохранение и загрузка данных: XmlSerializer).
Если вам все еще нужно/хотите писать, я бы написал в Application.persitentDataPath и прочитал/записал файл, используя FileStream
public void update(Action<bool> success)
{
StartCoroutine(UpdateRoutine(onSuccess));
}
private string authenticate(string username, string password)
{
string auth = username + ":" + password;
auth = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(auth));
auth = "Basic " + auth;
return auth;
}
private IEnumerator UpdateRoutine (Action<bool> onSuccess)
{
using(var www = UnityWebRequest.Get(_address_employeesXML)
{
string authorization = authenticate("YourUserName", "YourPassWord");
www.SetRequestHeader("AUTHORIZATION", authorization);
yield return www.SendRequest();
if (www.error)
{
success?.Invoke(false);
}
else
{
// you could ofcourse simply use the returned filecontent now like
var xml = www.downloadHandler.text;
var xmlSerializer = new XmlSerializer(typeof(YOURDATA_CLASS));
var dataClass = (YOURDATA_CLASS) xmlSerializer.Deserialize(xml);
success?.Invoke(true);
// However if you prefer to write the file
WriteFile(xml, success);
}
}
}
// Usually async void is bad
// but with a callback its fine
private async void WriteFile(string xml, Action<bool> success)
{
try
{
var data = Encoding.UTF8.GetBytes(xml);
using(var file = File.Open(Path.Combine(_filePathToXMLImport, "employees.xml", FileMode.OpenOrCreate))
{
await file.WriteAsync(data, 0, data.length);
success?.Invoke();
}
}
catch
{
success?.Invoke(false);
}
}
затем процесс чтения:
public void ReadFile(Action<bool> success)
{
using(var file = File.Open(Path.Combine(_filePathToXMLImport, "employees.xml", FileMode.Open))
{
var data = new byte[(int)file.length];
await file.ReadAsync(data, 0, data.length);
var xml = Encoding.UTF8.GetString(Data);
var xmlSerializer = new XMLSerializer(typeof(YOURDATA_CLASS));
var dataClass = (YOURDATA_CLASS) xmlSerializer.Deserialize(xml);
success?.Invoke(true);
}
}
Примечание. Набрано на смартфоне, поэтому гарантии нет, но я надеюсь, что идея понятна.
Спасибо за ответ. Я реализовал процесс асинхронной выборки. Я также пишу в Application.persitentDataPath, но, к сожалению, мне все еще нужно перезапустить приложение, чтобы обновить активы.
ваш код работал отлично, я просто выполнил его с ложной точки.
Решением моей проблемы стало перемещение упомянутого выше кода в класс Controller, отвечающий за StartView.
Можете ли вы опубликовать код? Что вы пробовали? Как мы можем решить вашу проблему без дополнительной информации?