これで十分な情報になるといいので、ここで説明します。あなたがより多くの情報を必要とするならば、lemmeはコメントで知っています。
2つの内部クラスを持つクラスがあります。内部クラスにはそれぞれ、外部クラスのメソッドを呼び出す2つのメソッドがあります。したがって、次のようになります。
public OuterClass {
private boolean outerMethodHasBeenCalled = false;
private void outerMethod() {
if(!outerMethodHasBeenCalled) {
// do stuff
}
outerMethodHasBeenCalled = true;
}
private FirstInnerClass {
public void someMethod() {
outerMethod();
}
}
private SecondInnerClass {
public void someOtherMethod() {
outerMethod();
}
}
}
次の点に注意することが重要です。
FirstInnerClass
とSecondInnerClass
のインスタンスはJavaScriptインターフェースとしてWebViewに渡されるため、someMethod
とsomeOtherMethod
は、特定の順序でいつでも呼び出すことができます。outerMethod
がほぼ同時に呼び出されます(ログメッセージを出力すると、1000分の1秒のタイムスタンプが付けられます) )さまざまなオブジェクトによって。 outerMethodHasBeenCalled
が呼び出されたときにouterMethod
がまだfalseであるため、私のアプリは '処理を2回行います'。これは大丈夫ではありません、そしてそれはまさに私が防ごうとしていることです。私のアプリは「何かをする」のは一度だけです。最初にouterMethod
が呼び出されたときです。OuterClass
のインスタンスが複数あるように聞こえるかもしれませんが、OuterClass
のインスタンスは1つだけですのでご安心ください。outerMethod
が最初に呼び出されたときだけ、私のアプリが「何かをする」ことが重要です(それが今では明らかであることを願っています)。以降のすべての呼び出しは基本的に無視されます。どちらの内部クラスが最初にouterMethod
を呼び出すかは関係ありません。
それで、この場合、synchronizedキーワードを使用するのは適切ですか?
うん、あなたが上にレイアウトしたものを考えると、私は一緒に行きます:
private synchronized void outerMethod() {
...
}
これには、outerMethod()が完了するまで呼び出し元の1つをブロックするという副作用があることに注意してください。それが許容できるなら、かっこいい。意図が単にouterMethod()のコードを一度実行することである場合、and最初の呼び出し元が遅れないように2番目の呼び出し元は問題ありませんがouterMethod()を実行している場合は、次のことを検討してください。
public OuterClass {
private AtomicBoolean outerMethodHasBeenCalled = new AtomicBoolean();
private void outerMethod() {
if (outerMethodHasBeenCalled.compareAndSet(false, true)) {
// do stuff
}
}
...
JavaDoc for AtomicBoolean を参照して、そこで何が起こっているかを調べてください(AndroidのJavaで利用可能であると想定しています)。
同期ブロックで1回だけ実行するすべてをouterMethod
でラップします。
private void outerMethod() {
synchronized (this) {
if(!outerMethodHasBeenCalled) {
// do stuff
}
outerMethodHasBeenCalled = true;
}
}
そうすれば、メソッドが最初に呼び出されたときに、一度に1つのスレッドのみが同期ブロックに入ることができます。最初のものはifステートメントのコードを実行し、次にouterMethodHasBeenCalled
をtrue
に設定します。他のスレッドはそれがtrueであることを確認し、ifコードをスキップします。