• Как подключить базу данных в приложение Xamarin.Forms?

    firedragon
    @firedragon
    Не джун-мидл-сеньор, а трус-балбес-бывалый.
    Опишу одно из своих:

    Бэкенд написанный на PHP давным давно.

    Xamarin.FORM приложение отображающиее разделы, подразделы и статьи.
    Приложение может сохранять все статьи для доступа в офлайне.

    Соответственно есть сервис который отдает одинаковые данные для обоих режимов.
    При попытке перехода в офлайн пользователю выводится предложение о скачивании всех ресурсов ок 60 мб.

    Дальше оно работает offline.

    Вот базовые классы

    using System;
    using System.IO;
    using System.Linq;
    using System.Threading.Tasks;
    using Polly;
    using SQLite;
    using Xamarin.Essentials;
    
    namespace SpecialForcesDirectory.Code
    {
        public abstract class BaseContentDatabase
        {
            public static readonly string DatabasePath = Path.Combine(FileSystem.AppDataDirectory, Settings.DataBaseName);
            static readonly Lazy<SQLiteAsyncConnection> DatabaseConnectionHolder = new Lazy<SQLiteAsyncConnection>(() => new SQLiteAsyncConnection(DatabasePath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.SharedCache));
    
            private static SQLiteAsyncConnection DatabaseConnection => DatabaseConnectionHolder.Value;
    
    
            protected static async ValueTask<SQLiteAsyncConnection> GetDatabaseConnection<T>()
            {
                if (DatabaseConnection.TableMappings.Any(x => x.MappedType == typeof(T))) return DatabaseConnection;
                // On sqlite-net v1.6.0+, enabling write-ahead logging allows for faster database execution
                await DatabaseConnection.EnableWriteAheadLoggingAsync().ConfigureAwait(false);
                await DatabaseConnection.CreateTablesAsync(CreateFlags.None, typeof(T)).ConfigureAwait(false);
                return DatabaseConnection;
            }
    
            public static Task<T> AttemptAndRetry<T>(Func<Task<T>> action, int numRetries = 10)
            {
                return Policy.Handle<SQLiteException>().WaitAndRetryAsync(numRetries, PollyRetryAttempt).ExecuteAsync(action);
    
                static TimeSpan PollyRetryAttempt(int attemptNumber) => TimeSpan.FromMilliseconds(Math.Pow(2, attemptNumber));
            }
    
            protected static async Task Close()
            {
                await DatabaseConnection.CloseAsync();
            }
        }
    public class ContentDatabase : BaseContentDatabase
        {
            #region Category repository
            private async Task<SQLiteAsyncConnection> GetCategoryConn()
            {
                return await GetDatabaseConnection<Category>().ConfigureAwait(false);
            }
            public async Task<IEnumerable<Category>> GetCategories()
            {
                var conn = await GetCategoryConn();
                return await AttemptAndRetry(() => conn.Table<Category>().ToListAsync()).ConfigureAwait(false);
            }
            public async Task<Category> GetCategory(int id)
            {
                var conn = await GetCategoryConn();
                return await AttemptAndRetry(() => conn.GetAsync<Category>(id)).ConfigureAwait(false);
            } 
            #endregion
    
            #region Content Repository
            private async Task<SQLiteAsyncConnection> GetCtxConn()
            {
                return await GetDatabaseConnection<Content>().ConfigureAwait(false);
            }
            
            public async Task<IEnumerable<Content>> GetItems()
            {
                var conn = await GetCtxConn();
                return await AttemptAndRetry(() => conn.Table<Content>().ToListAsync()).ConfigureAwait(false);
            }
    
            public async Task<Content> GetItem(int id)
            {
                var conn = await GetCtxConn();
                return await AttemptAndRetry(() => conn.GetAsync<Content>(id)).ConfigureAwait(false);
            }
    
            public async Task<int> DeleteItem(int id)
            {
                var conn = await GetCtxConn();
                return await AttemptAndRetry(() => conn.DeleteAsync<Content>(id)).ConfigureAwait(false);
            }
    
            public async Task SaveItem(Content item)
            {
                var conn = await GetCtxConn();
                if (item.Id == 0) await AttemptAndRetry(() => conn.InsertAsync(item)).ConfigureAwait(false);
                await AttemptAndRetry(() => conn.UpdateAsync(item)).ConfigureAwait(false);
            }
    
            public async Task<IEnumerable<SRawItem>> GetItemsByQuery(string q, int lim)
            {
                var qu = q.ToUpper();
                var list = new List<SRawItem>();
                var conn = await GetCtxConn();
                var result = conn.Table<Content>()
                    .Where(x => x.EnableTab1 == 1 && x.Tab1.ToUpper().Contains(qu)
                                || x.EnableTab2 == 1 && x.Tab2.ToUpper().Contains(qu)
                                || x.EnableTab3 == 1 && x.Tab3.ToUpper().Contains(qu)).Take(lim);
    
                var r = await result.ToListAsync();
                foreach (var content in r)
                {
                    var st = GetSt(content, qu);
                    var title = await conn.Table<Category>().Where(x => x.Id == content.CatId).FirstAsync();
                    var ni = new SRawItem
                    {
                        Body = st.Body,
                        CatId = content.CatId.ToString(),
                        Title = title.Title,
                        Id = content.Id.ToString(),
                        MType = "a",
                        Tab = st.Tab
                    };
                    list.Add(ni);
                }
    
                return list;
            }
    
            private static TabStruct GetSt(Content content, string q)
            {
                if (content.Tab1.ToUpper().Contains(q))
                    return new TabStruct { Tab = "1", Body = content.Tab1 };
                if (content.Tab2.ToUpper().Contains(q))
                    return new TabStruct { Tab = "2", Body = content.Tab2 };
                return new TabStruct { Tab = "3", Body = content.Tab3 };
            }
    
            private struct TabStruct
            {
                public string Body { get; set; }
                public string Tab { get; set; }
            }
    
            #endregion
    
            public async Task Clear()
            {
                await BaseContentDatabase.Close();
            }
        }
    [Table("quote")]
        public class Quote
        {
            [PrimaryKey]
            [AutoIncrement]
            [Column("id")] 
            public int Id { get; set; }
    
            [Column("author")] public string Author { get; set; }
    
            [Column("body")] public string Body { get; set; }
    
            [Column("image")] public string Image { get; set; }
    
            [Column("created")] public DateTime Created { get; set; }
        }
    
    public class QuoteRepository : BaseUserDatabase
        {
            private async Task<SQLiteAsyncConnection> GetConn()
            {
                return await GetDatabaseConnection<Quote>().ConfigureAwait(false);
            }
            public async Task<IEnumerable<Quote>> GetItems()
            {
                var conn = await GetConn();
                return await AttemptAndRetry(() => conn.Table<Quote>().ToListAsync()).ConfigureAwait(false);
            }
    
            public async Task<Quote> GetItem(int id)
            {
                var conn = await GetConn();
                return await AttemptAndRetry(() => conn.GetAsync<Quote>(id)).ConfigureAwait(false);
            }
    
            public async Task<int> DeleteItem(int id)
            {
                var conn = await GetConn();
                return await AttemptAndRetry(() => conn.DeleteAsync<Quote>(id)).ConfigureAwait(false);
            }
    
            public async Task<int> SaveItem(Quote item)
            {
                var conn = await GetConn();
                return await AttemptAndRetry(() => conn.InsertOrReplaceAsync(item)).ConfigureAwait(false);
            }
    
            public async Task DeleteAll()
            {
                var conn = await GetConn();
                await AttemptAndRetry(() => conn.DeleteAllAsync<Quote>()).ConfigureAwait(false);
            }
        }
    
    
    }
    Ответ написан
    Комментировать
  • Как сделать рулетку в unity3d?

    MrMureno
    @MrMureno Куратор тега Unity
    VR for all
    новые у вас и с этим кодом создадуться, тут проблем нету.

    а удалить старые. есть у вас
    GameObject obj - ссылка на объект.
    сохраните в классе ссылку на него (сейчас это локальная переменная в методе)
    (в вашем случае это будет массив ссылок или список)
    List<GameObject> objRefs  = new List<GameObject>();
    
    /////
    
    for ()
    {
    //вот вы создали объект и запоминаем в список
    objRefs.Add(obj);
    }
    
    /////удалить все из списка пройтись по списку
    foreach(var obj in objRefs)
    {
    Destroy(obj );
    }
    objRefs.Clear(); // и почистили список


    чистите старые объекты..в начале вашего метода к примеру.
    еще перед удаление объекта - можете проверить его на null, чтоб не пробовать удалять старые, вдруг они у вас самоуничтожаться могут или еще какая-то логика.

    Ну и так к слову..инстанциация дорогая операция, подумкйте над тем что возможно стоит создать все префабы на сцене и просто включать/выключать (может еще перемещать и настраивать) готовые уже объекты на сцене.
    Ответ написан
    3 комментария
  • Конвертор валют в кликер игре?

    neuotq
    @neuotq
    Прокрастинация
    Изучи это и пиши свой форматер для чисел.
    Ответ написан
    Комментировать