Я новичок в программировании на Android и не изучал Java ранее. Я действительно запутался в том, как использовать synchronized
для обеспечения безопасности потоков при static variables
:
Обычно я создаю класс с именем Utils
который имеет некоторые static functions
которые в большинстве случаев нужны всем моим другим классам. Это правильный способ сохранить повторяющийся код из моих классов.
У меня всегда возникает проблема с использованием баз данных. Когда я создаю класс sqliteHelper для определенной базы данных и пытаюсь управлять этой базой данных из службы Activity и Background, у меня обычно возникают проблемы. Если я использую локальные объекты вспомогательного класса, я максимально склонен к взаимоблокировке базы данных, когда оба вспомогательных объекта пытаются получить блокировку записи вместе.
Чтобы избавиться от этой проблемы, я создаю static
экземпляр класса-помощника в моем классе utils
. Теперь для выполнения любой операции с базой данных моя активность и моя служба делают следующее:
public class Utils{
public static MDatabaseHelper mHelper;
public static void instantiateHelper(Context context){
if(mHelper==null)
mHelper=new MDatabaseHelper(context);
}
}
public class mActivity extends Activity{
public void insert some item in database(final Item item) // this method is called in the Activity at some time
(new Thread(){
@Override public void run(){
Utils.instantiateHelper(getBaseContext());
mHelper.insertItem(item); }
}).start();
}
public class mService extends Service{
public void insert some item in database(final Item item) // this method is called in the service at some time
(new Thread(){
@Override public void run{
Utils.instantiateHelper(getBaseContext());
mHelper.insertItem(item); }
}).start();
}
Теперь, если и служба, и деятельность попытаются вставить элемент вместе. Я часто попадаю в эту ситуацию и возникает ошибка. Чтобы этого избежать, я использую этот способ:
Я помещаю операцию вставки в блок try и при отказе я жду случайного времени и повторю попытку
public void insertSomeItemInDatabase(final Item item)
(new Thread(){
@Override public void run(){
int i=0;
Random rand=new Random();
while(true){
if(i>10)
return;
try{
Utils.instantiateHelper(getBaseContext());
mHelper.insertItem(item);
break;
}catch(Exception e){
i++;
try{
Thread.sleep(rand.nextInt(1000));
}catch(Exception e){}
}
}
}
}
}).start();
}
Я знаю, что это самый худший метод синхронизации, но поскольку я настолько новичок в java
может кто-нибудь объяснить, как использовать synchronized
в этом сценарии.
Спасибо
Я думаю, что все, что вам нужно, - создать класс приложения
[1] Все эти переменные, которые вы использовали в Util, которые используются во всех других классах, могут быть взяты в этом классе Application. Таким образом, эти переменные будут доступны для всех других классов.
[2] Создать экземпляр Singelton класса Appliction. Просто Google об этом.
[3] Также создайте Singleton из DataBaseHelper (если это возможно и может применяться), поэтому один экземпляр помогает вам где угодно.
Класс приложения - это глобальный класс в android, поэтому вы можете использовать его для хранения и доступа ко всем глобальным данным. например:
public class AppData extends Application {
public static AppData appData;
public int currentUserId; // etc.
//Const.
public AppData() {
appData = this;
}
@Override
public void onCreate() {
super.onCreate();
loginPreferences = getSharedPreferences(
SPF_NAME, 0);
pathToSDCard = Environment.getExternalStorageDirectory().getAbsolutePath();
System.out.println("Path : " + pathToSDCard);
//etc.
}
// MOST IMP FOR GETTIN SINGELTON INSTANCE <<<---<<<---<<<---
public static AppData getAppData() {
return appData;
}
}
КАК ИСПОЛЬЗОВАТЬ ЭТО, СМОТРИТЕ ЭТО
class ABC extends Activity {
AppData appData;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xyz);
appData = AppData.getAppData();
...........
...........
appData.VARIABLE_NAME...
}
}
Еще одно. В AndroidMenifest.xml
...
...
<application // In Application Tag
android:name="PACKAGE_NAME.AppData" // << Add here class name in which you have extended Application
android:icon="@drawable/ic_launcher"
...
...